package com.alibaba.citrus.ots.application.report.ability.facade.job;

import com.alibaba.citrus.ots.application.report.ability.repository.BaseDataQueryRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.MonthSalesBasicReportQueryRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.MonthSalesBasicReportWriteRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.MonthSalesCategoryReportQueryRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.MonthSalesCategoryReportWriteRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.MonthSalesChannelRankReportQueryRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.MonthSalesChannelRankReportWriteRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.MonthSalesDepartmentRankReportQueryRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.MonthSalesDepartmentRankReportWriteRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.MonthSalesEmployeeRankReportQueryRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.MonthSalesEmployeeRankReportWriteRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.PlanContractQuantityRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.SalesOrderLineRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.SalesPlanDetailRepository;
import com.alibaba.citrus.ots.application.report.ability.utils.DomUtil;
import com.alibaba.citrus.ots.application.report.ability.utils.ObjectEqualsUtil;
import com.alibaba.citrus.ots.application.report.ability.utils.PageRecordUtil;
import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.util.DateUtils;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.StringUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.middleware.cache.runtime.service.EpochCacheService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.CategorySDO;
import com.epoch.app.bcorder.model.dto.EmployeeSDO;
import com.epoch.app.bcorder.model.dto.MonthSalesPlanProgressReportSDO;
import com.epoch.app.bcorder.model.dto.OrganizationSDO;
import com.epoch.app.bcorder.model.dto.ScItemSDO;
import com.epoch.app.bcorder.platform_enhance.SaleOrderTag;
import com.epoch.app.bcorder.sales_plan.contract.model.Contract;
import com.epoch.app.crb2btradecenter.model.dto.MonthSalesOrderCompleteSDO;
import com.epoch.app.crb2btradecenter.obtcsaleorderlineindex.model.ObtcSaleOrderLineIndex;
import com.epoch.app.crplatformenhance.enums.OrganizationTypeEnum;
import com.epoch.app.crplatformenhance.model.dto.GetDownOrganizationListRequest;
import com.epoch.app.crplatformenhance.sdo.CustomerAddressSDO;
import com.epoch.app.crplatformenhance.sdo.CustomerSDO;
import com.epoch.app.crplatformenhance.service.CrPlatformEnhanceService;
import com.epoch.app.otsapplicationreportsdk.contants.OtsApplicationReportSdkConstants;
import com.epoch.app.otsapplicationreportsdk.model.dto.BatchQueryContractQuantityRequest;
import com.epoch.app.otsapplicationreportsdk.model.dto.CommPageQueryRequest;
import com.epoch.app.otsapplicationreportsdk.model.dto.MonthSalesBasicReportSDO;
import com.epoch.app.otsapplicationreportsdk.model.dto.QueryMonthSalesReportRequest;
import com.epoch.app.otsapplicationreportsdk.model.enums.BizTypeEnum;
import com.epoch.app.otsapplicationreportsdk.model.enums.DataMarkEnum;
import com.epoch.app.otsapplicationreportsdk.monthsalesprogressreportwrite.dto.BatchGenerateAllMonthSalesReportJobRequest;
import com.epoch.app.otsapplicationreportsdk.monthsalesprogressreportwrite.dto.GenerateAllMonthSalesReportJobRequest;
import com.epoch.app.otsapplicationreportsdk.monthsalesprogressreportwrite.service.MonthSalesProgressReportWriteService;
import com.google.common.collect.Lists;
import lombok.Data;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.DoubleSummaryStatistics;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zhoubc
 * @description: TODO
 * @date 2021/12/27 15:35
 */
@Component
public class MonthSalesProgressReportSyncJob implements MonthSalesProgressReportWriteService {

    Log log = Log.getLogger(MonthSalesProgressReportSyncJob.class);

    private final String BASIC = "basicReport";
    private final String CHANNEL_RANK = "channelRank";
    private final String DEPARTMENT_RANK = "departmentRank";
    private final String EMPLOYEE_RANK = "employeeRank";
    private final String CATEGORY = "categoryReport";
    private final String ONE_CATEGORY = "oneCategoryReport";
    private final String TWO_CATEGORY = "twoCategoryReport";

    private final String REPORT_INCREMENTAL_COUNT_TIME = "report_incremental_count_time";

    @Resource
    BaseDataQueryRepository baseDataQueryRepository;
    @Resource
    MonthSalesBasicReportWriteRepository monthSalesBasicReportWriteRepository;
    @Resource
    MonthSalesBasicReportQueryRepository monthSalesBasicReportQueryRepository;
    @Resource
    SalesPlanDetailRepository salesPlanDetailRepository;
    @Resource
    SalesOrderLineRepository salesOrderLineRepository;
    @Resource
    PlanContractQuantityRepository contractQuantityRepository;
    @Resource
    MonthSalesEmployeeRankReportWriteRepository monthSalesEmployeeBankReportWriteRepository;
    @Resource
    MonthSalesDepartmentRankReportWriteRepository monthSalesDepartmentBankReportWriteRepository;
    @Resource
    MonthSalesChannelRankReportWriteRepository monthSalesChannelBankReportWriteRepository;
    @Resource
    MonthSalesCategoryReportWriteRepository monthSalesCategoryReportWriteRepository;
    @Resource
    MonthSalesEmployeeRankReportQueryRepository monthSalesEmployeeRankReportQueryRepository;
    @Resource
    MonthSalesDepartmentRankReportQueryRepository monthSalesDepartmentRankReportQueryRepository;
    @Resource
    MonthSalesChannelRankReportQueryRepository monthSalesChannelRankReportQueryRepository;
    @Resource
    MonthSalesCategoryReportQueryRepository monthSalesCategoryReportQueryRepository;
    @Resource
    CrPlatformEnhanceService crPlatformEnhanceService;

    @Resource(name="monthSalesReportTaskExecutor")
    ThreadPoolTaskExecutor monthSalesReportTaskExecutor;
    @Resource(name="monthSalesReportTaskExecutorSlowerMode")
    ThreadPoolTaskExecutor monthSalesReportTaskExecutorSlowerMode;
    @Resource(name="contractStatTaskExecutor")
    ThreadPoolTaskExecutor contractStatTaskExecutor;
    @Resource
    EpochCacheService epochCacheService;

    private static int PageSize_1000 = 1000;

    @Override
    @FacadeInvoker
    public Result<Void> generateAllMonthSalesReportJob(GenerateAllMonthSalesReportJobRequest generateAllMonthSalesReportJobRequest) {
        //初始化参数
        StopWatch stopWatch = new StopWatch("generateAllMonthSalesReportJob");
        stopWatch.start("init(generateAllMonthSalesReportJobRequest)");
        JobInitParam jobInitParam = init(generateAllMonthSalesReportJobRequest);
        log.info("generateAllMonthSalesReportJob_statisticalDate_println={}", jobInitParam.getThisDay());
        stopWatch.stop();
        //生成月度销售基础报表
        stopWatch.start("executeGenerateMonthSalesBasicReport");
        Boolean success = executeGenerateMonthSalesBasicReport(jobInitParam);
        stopWatch.stop();
        if (success) {
            //生成月度销售员工排名报表 (此时的排序号已废弃，查询时计算)
            stopWatch.start("executeGenerateEmployeeRankReport");
            CompletableFuture<Void> task1 = executeGenerateEmployeeRankReport(jobInitParam);
            stopWatch.stop();
            //生成月度销售部门排名报表 (此时的排序号已废弃，查询时计算)
            stopWatch.start("executeGenerateDepartmentRankReport");
            CompletableFuture<Void> task2 = executeGenerateDepartmentRankReport(jobInitParam);
            stopWatch.stop();
            //生成月度销售渠道排名报表 (此时的排序号已废弃，查询时计算)
            stopWatch.start("executeGenerateChannelRankReport");
            CompletableFuture<Void> task3 = executeGenerateChannelRankReport(jobInitParam);
            stopWatch.stop();
            //生成月度销售部门品类报表
            stopWatch.start("executeGenerateOneCategoryReport");
            CompletableFuture<Void> task4 = executeGenerateOneCategoryReport(jobInitParam);
            stopWatch.stop();
            stopWatch.start("executeGenerateTwoCategoryReport");
            CompletableFuture<Void> task5 = executeGenerateTwoCategoryReport(jobInitParam);
            stopWatch.stop();
            //增量统计报表  本身处理逻辑早已经用不了了且目前上线的分子公司数据不合预期，
//            stopWatch.start("executeGenerateAddDataReport");
//            CompletableFuture<Void> task6 = executeGenerateAddDataReport(jobInitParam);
//            stopWatch.stop();
            //等待所有任务执行完成
            stopWatch.start("CompletableFuture.allOf().join()");
            CompletableFuture.allOf(task1, task2, task3, task4, task5).join();
            stopWatch.stop();
        }
        log.info("generateAllMonthSalesReportJob_statisticalDate={}，consume={}，stopWatch={}", jobInitParam.getThisDay(), stopWatch.getTotalTimeMillis(), stopWatch.prettyPrint());
        return Result.success(null);
    }

    @FacadeInvoker
    private JobInitParam init(GenerateAllMonthSalesReportJobRequest jobRequest){
        //初始化日期参数
        Date todayDate = StringUtil.isNotEmpty(jobRequest.getStatisticalDate()) ? DateUtils.parse(jobRequest.getStatisticalDate()) : new Date();
        String thisDay = DateUtils.formatDate(todayDate, "yyyy-MM-dd");
        String thisMonth = DomUtil.getMonth(todayDate);
        String thisYear = DomUtil.getYear(todayDate);
        String thisMonthTimestamp = DomUtil.getMonthTimestamp(todayDate);
        //String aMonthAgo = DomUtil.getRollbackDate(todayDate,-31);

        //当天是否当月最终报表数据
        Integer isMonthDataMark = DomUtil.isLastDayOfMonth(todayDate)? DataMarkEnum.MONTH_FINAL_DATA.getCode():DataMarkEnum.MONTH_ACCUM_DATA.getCode();
        //当天是否第一次统计报表
        QueryMonthSalesReportRequest queryReportRequest = new QueryMonthSalesReportRequest();
        queryReportRequest.setStatisticalDate(thisDay);
        queryReportRequest.setStart(0);
        queryReportRequest.setLimit(1);
        // 查询月度销售进度基础报表
        PageResult<List<MonthSalesBasicReportSDO>> pageResult = monthSalesBasicReportQueryRepository.pageQueryList(queryReportRequest);
        Boolean isFirstSyncBasicReport = pageResult.getTotal() > 0 ? false : true;
        // 查询月度销售进度业务员排名报表
        PageResult<List<MonthSalesBasicReportSDO>> employeeBankList = monthSalesEmployeeRankReportQueryRepository.pageQueryList(queryReportRequest);
        Boolean isFirstSyncEmployeeRank = employeeBankList.getTotal() > 0 ? false : true;
        // 查询月度销售进度部门排名报表
        PageResult<List<MonthSalesBasicReportSDO>> departmentBankList = monthSalesDepartmentRankReportQueryRepository.pageQueryList(queryReportRequest);
        Boolean isFirstSyncDepartmentRank = departmentBankList.getTotal() > 0 ? false : true;
        // 查询月度销售进度渠道排名报表
        PageResult<List<MonthSalesBasicReportSDO>> channelBankList = monthSalesChannelRankReportQueryRepository.pageQueryList(queryReportRequest);
        Boolean isFirstSyncChannelRank = channelBankList.getTotal() > 0 ? false : true;
        // 查询月度销售进度品类排名报表
        PageResult<List<MonthSalesBasicReportSDO>> categoryReportList = monthSalesCategoryReportQueryRepository.pageQueryList(queryReportRequest);
        Boolean isFirstSyncCategoryReport = categoryReportList.getTotal() > 0 ? false : true;

        String enterpriseGroupOrgCode=OtsApplicationReportSdkConstants.ENTERPRISE_GROUP_ORG_CODE()!=null?OtsApplicationReportSdkConstants.ENTERPRISE_GROUP_ORG_CODE():"6000";
        Map<String, OrganizationSDO> orgMap = baseDataQueryRepository.batchQueryOrganizationByOutCodes(Lists.newArrayList(enterpriseGroupOrgCode));

        JobInitParam jobInitParam = new JobInitParam();
        jobInitParam.setTodayDate(todayDate);
        jobInitParam.setThisDay(thisDay);
        jobInitParam.setThisMonth(thisMonth);
        jobInitParam.setThisYear(thisYear);
        jobInitParam.setThisMonthTimestamp(thisMonthTimestamp);
        jobInitParam.setIsMonthDataMark(isMonthDataMark);
        jobInitParam.setIsFirstSyncBasicReport(isFirstSyncBasicReport);
        jobInitParam.setIsFirstSyncEmployeeRank(isFirstSyncEmployeeRank);
        jobInitParam.setIsFirstSyncDepartmentRank(isFirstSyncDepartmentRank);
        jobInitParam.setIsFirstSyncChannelRank(isFirstSyncChannelRank);
        jobInitParam.setIsFirstSyncCategoryReport(isFirstSyncCategoryReport);
        jobInitParam.setMonth(String.valueOf(DomUtil.getMonthNum(todayDate)));
        jobInitParam.setEnterpriseGroupOrgId(orgMap.get(enterpriseGroupOrgCode)!=null?orgMap.get(enterpriseGroupOrgCode).getId():null);
        if(jobRequest.getSlowerMode()!=null){
            jobInitParam.setSlowerMode(jobRequest.getSlowerMode());
        }

        if(jobInitParam.getSlowerMode()){
            log.info("OtsApplicationReportSdkConstants_query_readonly_database={},slowerMode={},thread_pool_core_size={},thread_pool_max_size={}", OtsApplicationReportSdkConstants.QUERY_READONLY_DATABASE(),jobInitParam.getSlowerMode(),monthSalesReportTaskExecutorSlowerMode.getCorePoolSize(),monthSalesReportTaskExecutorSlowerMode.getMaxPoolSize());
        }else{
            log.info("OtsApplicationReportSdkConstants_query_readonly_database={},slowerMode={},thread_pool_core_size={},thread_pool_max_size={}", OtsApplicationReportSdkConstants.QUERY_READONLY_DATABASE(),jobInitParam.getSlowerMode(),monthSalesReportTaskExecutor.getCorePoolSize(),monthSalesReportTaskExecutor.getMaxPoolSize());
        }
        return jobInitParam;
    }

    private boolean executeGenerateMonthSalesBasicReport(JobInitParam jobInitParam){
        if(StringUtils.isBlank(jobInitParam.getEnterpriseGroupOrgId())){
            return false;
        }
        //查询常温事业部6000下所有分子公司组织
        GetDownOrganizationListRequest getDownOrganizationListRequest = new GetDownOrganizationListRequest();
        getDownOrganizationListRequest.setId(jobInitParam.getEnterpriseGroupOrgId());
        getDownOrganizationListRequest.setType(OrganizationTypeEnum.COMPANY.getCode());
        Result<List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO>> mnCompanyOrgList = crPlatformEnhanceService.getDownOrganizationList(getDownOrganizationListRequest);
        List<Future<Map<String,Object>>> futureList = Lists.newArrayList();
        log.info("executeGenerateMonthSalesBasicReport_orgs_size={}", mnCompanyOrgList.getResult().size());
        for(com.epoch.app.crplatformenhance.sdo.OrganizationSDO org : mnCompanyOrgList.getResult()){
            String companyOrgId = org.getId();
            CompletableFuture<Map<String,Object>> future = CompletableFuture.supplyAsync(() -> {
                StopWatch sw = new StopWatch();
                sw.start();

                Map<String,Object> result = new HashMap<>();
                result.put("orgId",companyOrgId);
                result.put("planListSize",0);
                result.put("contractListSize",0);
                result.put("orderListSize",0);
                //查询对应的销售组织
                com.epoch.app.crplatformenhance.sdo.OrganizationSDO salesOrg = getSalesOrgByCompanyOrgId(companyOrgId);
                if(salesOrg == null){
                    return result;
                }
                //取月度计划数据
                List<MonthSalesPlanProgressReportSDO> getSalePlanDataList = getSalePlanDataList(jobInitParam, companyOrgId);
                log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_pull_data_plan_size={}", companyOrgId, getSalePlanDataList.size());
                //取合同金额数据
                List<Contract> getPlanContractDataList = getPlanContractDataList(jobInitParam, companyOrgId);
                log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_pull_data_contract_size={}", companyOrgId, getPlanContractDataList.size());
                //取销售订单数据es
                List<ObtcSaleOrderLineIndex> getSaleOrderDataList = getSaleOrderDataList(jobInitParam, salesOrg.getId());
                log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_pull_data_order_size={},salesOrgId={}", companyOrgId, getSaleOrderDataList.size(), salesOrg.getId());

                //无数据，不处理
                if(CollectionUtils.isEmpty(getSalePlanDataList) && CollectionUtils.isEmpty(getPlanContractDataList) && CollectionUtils.isEmpty(getSaleOrderDataList)){
                    log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_pull_data_all_empty", companyOrgId);
                    return result;
                }

                try {
                    //合并月度计划+销售订单+合同金额
                    List<MonthSalesBasicReportSDO> mergeList = buildBasicReportList(jobInitParam, getSalePlanDataList, getSaleOrderDataList, getPlanContractDataList, companyOrgId);
                    log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_merge_data_mergeList_size={}", companyOrgId, mergeList.size());
                    //填充主数据
                    enrichName(mergeList);

                    if (jobInitParam.getIsFirstSyncBasicReport()) {
                        log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_batchCreate_size={}", companyOrgId, mergeList.size());
                        monthSalesBasicReportWriteRepository.batchCreate(mergeList);
                    } else {
                        Map<String, MonthSalesBasicReportSDO> mergeMap = mergeList.stream().collect(Collectors.toMap(x -> fetchKey(x), Function.identity(), (v1, v2) -> v1));
                        List<MonthSalesBasicReportSDO> batchDeleteList = new ArrayList<>();
                        //比较旧报表数据
                        compareOldBasicReport(companyOrgId, jobInitParam.getThisDay(), batchDeleteList, mergeMap);

                        //统计得到存在多余数据，删除
                        log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_need_delete_list={}", companyOrgId, JSON.toJSONString(batchDeleteList));
                        if (CollectionUtils.isNotEmpty(batchDeleteList)) {
                            List<Long> ids = batchDeleteList.stream().map(x -> Long.valueOf(x.getId())).collect(Collectors.toList());
                            Integer count = monthSalesBasicReportWriteRepository.batchDelete(ids);
                            log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_delete_request={},success_result={},statisticalDate={}", companyOrgId, JSON.toJSONString(ids), count, jobInitParam.getThisDay());
                        }

                        //批量创建新key报表数据
                        List<MonthSalesBasicReportSDO> createList = mergeMap.values().stream().filter(x -> x.getHasProcess()==null || !x.getHasProcess()).collect(Collectors.toList());
                        log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_need_batch_create_size={}", companyOrgId, createList.size());
                        if (CollectionUtils.isNotEmpty(createList)) {
                            monthSalesBasicReportWriteRepository.batchCreate(createList);
                        }
                    }
                } catch (Throwable e) {
                    log.error("salesReportSubtask"+companyOrgId+"=executeGenerateMonthSalesBasicReport_future_occor_error ",  e);
                }
                sw.stop();
                log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_finish_elapsed_time={}", companyOrgId, sw.getTotalTimeMillis());

                result.put("planListSize",getSalePlanDataList.size());
                result.put("contractListSize",getPlanContractDataList.size());
                result.put("orderListSize",getSaleOrderDataList.size());
                return result;
            },jobInitParam.getSlowerMode()?monthSalesReportTaskExecutorSlowerMode:monthSalesReportTaskExecutor);
            futureList.add(future);
        }
        List<Map<String,Object>> todoList = new ArrayList<>();
        for (Future<Map<String,Object>> future : futureList) {
            Map result = null;
            try {
                result = future.get();
                todoList.add(result);
            } catch (Exception e) {
                log.error("executeGenerateMonthSalesBasicReport_future_deal_get_occar_error ",e);
            }
        }
        //任务生成的重复数据 ，删除
        List<Long> ids = monthSalesBasicReportQueryRepository.statisticalRepeatKey(jobInitParam.getThisDay());
        if(CollectionUtils.isNotEmpty(ids)){
            Integer count = monthSalesBasicReportWriteRepository.batchDelete(ids);
            log.error("executeGenerateMonthSalesBasicReport_statisticalRepeatKey_ids={},count={}",JSONObject.toJSON(ids),count);
        }

        int planSum = todoList.stream().mapToInt(x->(int)x.get("planListSize")).sum();
        int contractSum = todoList.stream().mapToInt(x->(int)x.get("contractListSize")).sum();
        int orderSum = todoList.stream().mapToInt(x->(int)x.get("orderListSize")).sum();
        log.info("executeGenerateMonthSalesBasicReport_finish_result={},planSum={},contractSum={},orderSum={}",todoList,planSum,contractSum,orderSum);
        return true;
    }

    @FacadeInvoker
    private CompletableFuture<Void> executeGenerateAddDataReport(JobInitParam jobInitParam){
        return CompletableFuture.runAsync(() -> {
            //统计日期不是今天，不做增量统计
            if(!jobInitParam.getThisDay().equals(DomUtil.getToday())){
                log.info("executeGenerateMonthSalesAddDataReport_statisticalDate_is_not_today_return");
                return;
            }
            //增量更新统计报表 (创建日期,(客户x货品Key,order)SDO)
            Map<String, List<MonthSalesOrderCompleteSDO>> map = getAddSaleOrderDataMap(jobInitParam);
            log.info("executeGenerateMonthSalesAddDataReport_getAddSaleOrderDataMap_result=={}",map);

            for (Map.Entry<String, List<MonthSalesOrderCompleteSDO>> m : map.entrySet()) {
                String gmtCreate = m.getKey();
                //某个创建日期且已完成的订单数据需要更新   订单创建日期~当前日期昨天 的统计更新
                List<MonthSalesOrderCompleteSDO> newAddOrderList = m.getValue();

                Date gmtCreateDate = DateUtils.parse(gmtCreate);
                String endDate = jobInitParam.getThisMonth().equals(DomUtil.getMonth(gmtCreateDate))?
                        DomUtil.getYesterdayByDate(DateUtils.parse(jobInitParam.getThisDay())):DomUtil.getLastDayMonth(gmtCreateDate);
                //String endDate = DomUtil.getYesterdayByDate(DateUtils.parse(jobInitParam.getThisDay()));

                QueryMonthSalesReportRequest request = new QueryMonthSalesReportRequest();
                request.setBeginDate(gmtCreate);
                request.setEndDate(endDate);
                newAddOrderList.forEach(x -> {
                    request.setScItemCode(x.getScItemId());
                    request.setCustomerCode(x.getCustomerCode());
                    request.setCustomerAddressCode(x.getCustomerAddressCode());
                    List<MonthSalesBasicReportSDO> reportList = monthSalesBasicReportQueryRepository.getMonthSalesBasicReportList(request);
                    log.info("executeGenerateMonthSalesAddDataReport_query_updateOrderList,request={},response={}", JSONObject.toJSON(request), JSONObject.toJSON(reportList));
                    long minTime = DateUtils.parse(gmtCreate).getTime();
                    long maxTime = DateUtils.parse(endDate).getTime();
                    Date cycleDate = DateUtils.parse(gmtCreate);
                    //多个不同日期,相同货品x客户Key,,要更新
                    while(cycleDate.getTime() >= minTime && cycleDate.getTime() <= maxTime){
                        String str = DateUtils.toDateStr(cycleDate,"yyyy-MM-dd");
                        List<MonthSalesBasicReportSDO> oldReportList = Nullable.stream(reportList).filter(sdo -> sdo.getStatisticalDate().equals(str)).collect(Collectors.toList());
                        MonthSalesBasicReportSDO sdo = null;
                        if(CollectionUtils.isNotEmpty(oldReportList)){
                            //更新基础报表
                            sdo = oldReportList.get(0);
                            resetCountOrder(sdo, x);
                            Integer count = monthSalesBasicReportWriteRepository.update(sdo);
                            log.info("executeGenerateMonthSalesAddDataReport_basic_history_update={},size={}", JSON.toJSONString(sdo), count);
                        }else{
                            //新增报表数据
                            x.setCreateDate(str);
                            sdo = resetCountCreateReport(x);
                            String id = monthSalesBasicReportWriteRepository.create(sdo);
                            log.info("executeGenerateMonthSalesAddDataReport_basic_history_create={},id={}", JSON.toJSONString(sdo),id);
                        }

                        //更新渠道排名报表
                        QueryMonthSalesReportRequest queryRequest = new QueryMonthSalesReportRequest();
                        queryRequest.setStatisticalDate(sdo.getStatisticalDate());
                        queryRequest.setOrgBusinessUnitId(sdo.getOrgBusinessUnitId());
                        queryRequest.setOrgSalesOrganizationId(sdo.getOrgSalesOrganizationId());
                        queryRequest.setOrgSalesChannelId(sdo.getOrgSalesChannelId());
                        List<MonthSalesBasicReportSDO> channelRankReportReport = monthSalesChannelRankReportQueryRepository.getChannelBankReportList(queryRequest);
                        if (CollectionUtils.isNotEmpty(channelRankReportReport)) {
                            MonthSalesBasicReportSDO channelRankSDO = channelRankReportReport.get(0);
                            resetCountOrder(channelRankSDO, x);
                            Integer count = monthSalesChannelBankReportWriteRepository.update(channelRankSDO);
                            log.info("executeGenerateMonthSalesAddDataReport_channel_history_update={},size={}", JSON.toJSONString(channelRankSDO), count);
                        }else{
                            monthSalesChannelBankReportWriteRepository.add(sdo);
                        }

                        //更新部门排名报表
                        queryRequest.setOrgSalesDepartmentId(sdo.getOrgSalesDepartmentId());
                        List<MonthSalesBasicReportSDO> departmentRankReport = monthSalesDepartmentRankReportQueryRepository.getDepartmentBankReportList(queryRequest);
                        if (CollectionUtils.isNotEmpty(departmentRankReport)) {
                            MonthSalesBasicReportSDO departmentRankSDO = departmentRankReport.get(0);
                            resetCountOrder(departmentRankSDO, x);
                            Integer count = monthSalesDepartmentBankReportWriteRepository.update(departmentRankSDO);
                            log.info("executeGenerateMonthSalesAddDataReport_department_history_update={},size={}", JSON.toJSONString(departmentRankSDO), count);
                        }else{
                            monthSalesDepartmentBankReportWriteRepository.add(sdo);
                        }

                        //更新员工排名报表
                        queryRequest.setManageEmployeeId(sdo.getManageEmployeeId());
                        List<MonthSalesBasicReportSDO> employeeRankReport = monthSalesEmployeeRankReportQueryRepository.getEmployeeBankReportList(queryRequest);
                        if (CollectionUtils.isNotEmpty(employeeRankReport)) {
                            MonthSalesBasicReportSDO employeeRankSDO = employeeRankReport.get(0);
                            resetCountOrder(employeeRankSDO, x);
                            Integer count = monthSalesEmployeeBankReportWriteRepository.update(employeeRankSDO);
                            log.info("executeGenerateMonthSalesAddDataReport_employee_history_update={},size={}", JSON.toJSONString(employeeRankSDO), count);
                        }else{
                            monthSalesEmployeeBankReportWriteRepository.add(sdo);
                        }

                        //更新类目报表
                        queryRequest.setScItemCategoryId(sdo.getScItemRootCategoryId());
                        queryRequest.setBizType(BizTypeEnum.ONE_CATEGORY.getCode());
                        List<MonthSalesBasicReportSDO> categoryReport = monthSalesCategoryReportQueryRepository.getCategoryReportList(queryRequest);
                        if (CollectionUtils.isNotEmpty(categoryReport)) {
                            MonthSalesBasicReportSDO categorySDO1 = categoryReport.get(0);
                            resetCountOrder(categorySDO1, x);
                            Integer count = monthSalesCategoryReportWriteRepository.update(categorySDO1);
                            log.info("executeGenerateMonthSalesAddDataReport_one_category_history_update={},size={}", JSON.toJSONString(categorySDO1), count);
                        }else{
                            sdo.setBizType(BizTypeEnum.ONE_CATEGORY.getCode());
                            sdo.setScItemCategoryId(sdo.getScItemRootCategoryId());
                            sdo.setScItemCategoryName(sdo.getScItemRootCategoryName());
                            monthSalesCategoryReportWriteRepository.add(sdo);
                        }

                        queryRequest.setScItemCategoryId(sdo.getScItemLeafCategoryId());
                        queryRequest.setBizType(BizTypeEnum.TWO_CATEGORY.getCode());
                        List<MonthSalesBasicReportSDO> categoryReport1 = monthSalesCategoryReportQueryRepository.getCategoryReportList(queryRequest);
                        if (CollectionUtils.isNotEmpty(categoryReport1)) {
                            MonthSalesBasicReportSDO categorySDO2 = categoryReport1.get(0);
                            resetCountOrder(categorySDO2, x);
                            Integer count = monthSalesCategoryReportWriteRepository.update(categorySDO2);
                            log.info("executeGenerateMonthSalesAddDataReport_two_category_history_update={},size={}", JSON.toJSONString(categorySDO2), count);
                        }else{
                            sdo.setBizType(BizTypeEnum.TWO_CATEGORY.getCode());
                            sdo.setScItemCategoryId(sdo.getScItemLeafCategoryId());
                            sdo.setScItemCategoryName(sdo.getScItemLeafCategoryName());
                            monthSalesCategoryReportWriteRepository.add(sdo);
                        }

                        cycleDate = DateUtils.parse(DomUtil.getRollbackDate(cycleDate,1));
                    }
                });
            }
        }, monthSalesReportTaskExecutor);
    }

    //并行拉取月度计划数据
    private List<MonthSalesPlanProgressReportSDO> getSalePlanDataList(JobInitParam jobInitParam, String orgBusinessUnitCode) {
        List<Future<List<MonthSalesPlanProgressReportSDO>>> futureList = Lists.newArrayList();
        int total = getSalePlanDataTotal(jobInitParam, orgBusinessUnitCode);
        int totalPage = total / PageSize_1000;
        if (total % PageSize_1000 > 0) {
            totalPage++;
        }
        for (int pageNo = 0; pageNo < totalPage; pageNo++) {
            int start = pageNo * PageSize_1000;
            String planTime = jobInitParam.getThisMonthTimestamp();
            CompletableFuture<List<MonthSalesPlanProgressReportSDO>> future = CompletableFuture.supplyAsync(() -> {
                PageResult<List<MonthSalesPlanProgressReportSDO>> planPageResult = null;
                try {
                    CommPageQueryRequest request = new CommPageQueryRequest();
                    request.setPlanMonth(planTime);
                    request.setOrgBusinessUnitCode(orgBusinessUnitCode);
                    request.setStart(start);
                    request.setLimit(PageSize_1000);
                    planPageResult = salesPlanDetailRepository.pageStatisticalMonthPlanProgressData(request);
                    if (planPageResult == null || CollectionUtils.isEmpty(planPageResult.getContent())) {
                        return Lists.newArrayList();
                    }
                } catch (Exception e) {
                    log.error("pageStatisticalMonthPlanProgressData_query_error ", e);
                    return Lists.newArrayList();
                }
                return planPageResult.getContent();
            }, contractStatTaskExecutor);
            futureList.add(future);
        }
        List<MonthSalesPlanProgressReportSDO> result = new ArrayList<>();
        try {
            for (Future<List<MonthSalesPlanProgressReportSDO>> future : futureList) {
                List<MonthSalesPlanProgressReportSDO> subList = future.get();
                result.addAll(subList);
            }
        } catch (Exception e) {
            log.error("pageStatisticalMonthPlanProgressData_query_error_get_result_error ", e);
        }
        return result;
    }

    //并行拉取销售订单数据
    private List<ObtcSaleOrderLineIndex> getSaleOrderDataList(JobInitParam jobInitParam, String orgSalesOrganizationCode){
        List<Future<List<ObtcSaleOrderLineIndex>>> futureList = Lists.newArrayList();
        int total = getSaleOrderDataTotal(jobInitParam, orgSalesOrganizationCode);
        int totalPage = total/PageSize_1000;
        if (total%PageSize_1000>0){
            totalPage++;
        }
        for (int pageNo = 0; pageNo < totalPage; pageNo++) {
            int start = pageNo*PageSize_1000;
            String beginTime = jobInitParam.getThisMonth()+"-01 00:00:00";
            String endTime = jobInitParam.getThisDay()+" 23:59:59";
            CompletableFuture<List<ObtcSaleOrderLineIndex>> future = CompletableFuture.supplyAsync(() -> {
                CommPageQueryRequest queryRequest = new CommPageQueryRequest();
                queryRequest.setOrgSalesOrganizationCode(orgSalesOrganizationCode);
                queryRequest.setBeginDate(beginTime);
                queryRequest.setEndDate(endTime);
                queryRequest.setStart(start);
                queryRequest.setLimit(PageSize_1000);
                Result<List<ObtcSaleOrderLineIndex>> result = null;
                try {
                    result = salesOrderLineRepository.statisticalMonthSalesOrderCompleteData(queryRequest);
                    if (result==null || CollectionUtils.isEmpty(result.getResult())){
                        return Lists.newArrayList();
                    }
                    log.info("statisticalMonthSalesOrderCompleteData_query_request={},result_size={}", JSON.toJSONString(queryRequest),result.getResult().size());
                } catch (Exception e) {
                    log.error("statisticalMonthSalesOrderCompleteData_query_error ", e);
                    return Lists.newArrayList();
                }
                return result.getResult();
            }, contractStatTaskExecutor);
            futureList.add(future);
        }
        List<ObtcSaleOrderLineIndex> result = new ArrayList<>();
        try {
            for (Future< List<ObtcSaleOrderLineIndex>> future : futureList){
                List<ObtcSaleOrderLineIndex> subList = future.get();
                result.addAll(subList);
            }
        }catch (Exception e){
            log.error("statisticalMonthSalesOrderCompleteData_query_error_get_result_error ", e);
        }
        return result;
    }

    //并行拉取计划合同数据
    private List<Contract> getPlanContractDataList(JobInitParam jobInitParam, String orgBusinessUnitCode){
        List<Future<List<Contract>>> futureList = Lists.newArrayList();
        int total = getPlanContractDataTotal(jobInitParam, orgBusinessUnitCode);
        int totalPage = total/PageSize_1000;
        if (total%PageSize_1000>0){
            totalPage++;
        }
        for (int pageNo = 0; pageNo < totalPage; pageNo++) {
            int start = pageNo*PageSize_1000;
            CompletableFuture<List<Contract>> future = CompletableFuture.supplyAsync(() -> {
                BatchQueryContractQuantityRequest queryRequest = new BatchQueryContractQuantityRequest();
                queryRequest.setContractYear(jobInitParam.getThisYear());
                queryRequest.setOrgBusinessUnitCode(orgBusinessUnitCode);
                queryRequest.setStart(start);
                queryRequest.setLimit(PageSize_1000);
                Result<List<Contract>> result = null;
                try {
                    result = contractQuantityRepository.pageQueryContractMoney(queryRequest);
                    if (result==null || CollectionUtils.isEmpty(result.getResult())){
                        return Lists.newArrayList();
                    }
                } catch (Exception e) {
                    log.error("pageQueryContractMoney_query_error ", e);
                    return Lists.newArrayList();
                }
                return result.getResult();
            }, contractStatTaskExecutor);
            futureList.add(future);
        }
        List<Contract> result = new ArrayList<>();
        try {
            for (Future< List<Contract>> future : futureList){
                List<Contract> subList = future.get();
                result.addAll(subList);
            }
        }catch (Exception e){
            log.error("pageQueryContractMoney_query_error_get_result_error ", e);
        }
        return result;
    }

    private com.epoch.app.crplatformenhance.sdo.OrganizationSDO getSalesOrgByCompanyOrgId(String companyOrgId){
        GetDownOrganizationListRequest getDownOrganizationListRequest = new GetDownOrganizationListRequest();
        getDownOrganizationListRequest.setId(companyOrgId);
        getDownOrganizationListRequest.setType(OrganizationTypeEnum.SALES_ORGANIZATION.getCode());
        Result<List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO>> salesOrgs = crPlatformEnhanceService.getDownOrganizationList(getDownOrganizationListRequest);
        List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO> filterSalesOrgs = Nullable.stream(salesOrgs.getResult()).filter(x->x.getName().contains("销售组织")).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(filterSalesOrgs)){
            return filterSalesOrgs.get(0);
        }
        return null;
    }

    //获取销售订单?天内的每日订单量和累计订单量  (客户x货品,日期,SDO)
    @FacadeInvoker
    private Map<String, List<MonthSalesOrderCompleteSDO>> getAddSaleOrderDataMap(JobInitParam jobInitParam){
        //获取?天内的客户x货品明细每日订单量
        List<ObtcSaleOrderLineIndex> lines = getAddSaleOrderDataList(jobInitParam);
        log.info("executeGenerateMonthSalesAddDataReport_getAddSaleOrderDataList_result_size=={}",lines.size());
        if(CollectionUtils.isEmpty(lines)){
            return new HashMap<>();
        }
        //过滤掉当天创建日期的订单
        String thisDay = jobInitParam.getThisDay();
        lines = Nullable.stream(lines).filter(x -> !thisDay.equals(DomUtil.stampToDate(x.getSubGmtCreate()))).collect(Collectors.toList());
        log.info("executeGenerateMonthSalesAddDataReport_getAddSaleOrderDataList_filter_result_size=={},{}",lines.size(),lines);
        if(CollectionUtils.isEmpty(lines)){
            return new HashMap<>();
        }
        List<MonthSalesOrderCompleteSDO> orderList = new ArrayList<>();
        for (ObtcSaleOrderLineIndex line:lines) {
            BigDecimal amount = new BigDecimal(0);
            BigDecimal beforeAmount = new BigDecimal(0);
            BigDecimal invoiceZk01 = new BigDecimal(0);
            if (StringUtils.isNotBlank(line.getSubDeliveryAmount())) {
                amount = new BigDecimal(line.getSubDeliveryAmount());
            }
            if (StringUtils.isNotBlank(line.getSubDctBeforePrice())) {
                beforeAmount = new BigDecimal(line.getSubDctBeforePrice()).multiply(amount).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            }
            if (StringUtils.isNotBlank(line.getSubInvoiceZK01())) {
                invoiceZk01 = new BigDecimal(line.getSubInvoiceZK01()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            }

            BigDecimal taskCount = new BigDecimal(0);
            BigDecimal beforeMonthMoneyComplete = new BigDecimal(0);
            BigDecimal monthMoneyComplete = new BigDecimal(0);
            //标准退货订单
            if(SaleOrderTag.STD_RETURN_ORDER.getCode().equals(line.getMainOrderType())) {
                taskCount = taskCount.subtract(amount);
                beforeMonthMoneyComplete = beforeMonthMoneyComplete.subtract(beforeAmount);
                monthMoneyComplete = monthMoneyComplete.subtract(invoiceZk01);
                //标准订单，车销订单，现金订单
            }else{
                taskCount = taskCount.add(amount);
                beforeMonthMoneyComplete = beforeMonthMoneyComplete.add(beforeAmount);
                monthMoneyComplete = monthMoneyComplete.add(invoiceZk01);
            }

            MonthSalesOrderCompleteSDO sdo = new MonthSalesOrderCompleteSDO();
            sdo.setOrgBusinessUnitCode(line.getMainBisUnitCode());
            sdo.setOrgSalesOrganizationCode(line.getMainOrganizationCode());
            sdo.setOrgSalesChannelCode(line.getMainSaleChannelCode());
            sdo.setOrgSalesDepartmentCode(line.getMainDepartmentCode());
            sdo.setManageEmployeeId(line.getMainSalesmanId());
            sdo.setCustomerCode(line.getMainCustomerCode());
            sdo.setCustomerAddressCode(line.getMainReceiveAddressCode());
            sdo.setScItemId(line.getSubScItemId());
            sdo.setGmtCreate(line.getSubGmtCreate());
            sdo.setTaskCountComplete(taskCount.longValue());
            sdo.setBeforeMonthMoneyComplete(beforeMonthMoneyComplete);
            sdo.setMonthMoneyComplete(monthMoneyComplete);
            orderList.add(sdo);
        }

        //处理数据 生成(创建日期,(客户x货品Key,order)SDO)维度
        Map<String, List<MonthSalesOrderCompleteSDO>> resultMap = new HashMap<>();
        Map<String, List<MonthSalesOrderCompleteSDO>> gmtCreateGroupBy = orderList.stream().collect(Collectors.groupingBy(e -> DomUtil.stampToDate(e.getGmtCreate())));
        for (Map.Entry<String, List<MonthSalesOrderCompleteSDO>> m : gmtCreateGroupBy.entrySet()) {
            String gmtCreate = m.getKey(); //yyyy-MM-dd
            List<MonthSalesOrderCompleteSDO> list = m.getValue();
            //客户x货品Key
            Map<String, LongSummaryStatistics> sumTaskCountComplete = list.stream().collect(Collectors.groupingBy(e -> fetchKey(e),Collectors.summarizingLong(e -> e.getTaskCountComplete())));
            Map<String, DoubleSummaryStatistics> sumBeforeMonthMoneyComplete = list.stream().collect(Collectors.groupingBy(e -> fetchKey(e),Collectors.summarizingDouble(e -> e.getBeforeMonthMoneyComplete().doubleValue())));
            Map<String, DoubleSummaryStatistics> sumMonthMoneyComplete = list.stream().collect(Collectors.groupingBy(e -> fetchKey(e),Collectors.summarizingDouble(e -> e.getMonthMoneyComplete().doubleValue())));
            List<MonthSalesOrderCompleteSDO> tmp = new ArrayList<>();
            for (Map.Entry<String, LongSummaryStatistics> m2 : sumTaskCountComplete.entrySet()) {
                String custAndItemKey = m2.getKey();
                String[] array = custAndItemKey.split("#");
                LongSummaryStatistics statistics= m2.getValue();

                List<MonthSalesOrderCompleteSDO> filterList = list.stream().filter(x -> fetchKey(x).equals(custAndItemKey)).collect(Collectors.toList());
                if(CollectionUtils.isEmpty(filterList)){
                    log.warn("executeGenerateMonthSalesAddDataReport_statistic_gmtCreateGroupBy_certainSdo_is_null,key={}",custAndItemKey);
                    continue;
                }
                MonthSalesOrderCompleteSDO certainSdo = filterList.get(0);

                long taskCountComplete = statistics.getSum();
                BigDecimal beforeMonthMoneyComplete = new BigDecimal(sumBeforeMonthMoneyComplete.get(custAndItemKey).getSum());
                BigDecimal monthMoneyComplete = new BigDecimal(sumMonthMoneyComplete.get(custAndItemKey).getSum());
                if(statistics.getSum() != 0 && beforeMonthMoneyComplete.compareTo(BigDecimal.ZERO) == 0 && monthMoneyComplete.compareTo(BigDecimal.ZERO) == 0){
                    log.info("executeGenerateMonthSalesAddDataReport_statistic_key_taskCountComplete_is_zero,key={}",custAndItemKey);
                }

                MonthSalesOrderCompleteSDO sdo = new MonthSalesOrderCompleteSDO();
                sdo.setOrgBusinessUnitCode(certainSdo.getOrgBusinessUnitCode());
                sdo.setOrgSalesOrganizationCode(certainSdo.getOrgSalesOrganizationCode());
                sdo.setOrgSalesChannelCode(certainSdo.getOrgSalesChannelCode());
                sdo.setOrgSalesDepartmentCode(certainSdo.getOrgSalesDepartmentCode());
                sdo.setManageEmployeeId(certainSdo.getManageEmployeeId());
                sdo.setScItemId(array[0]);
                sdo.setCustomerCode(array[1]);
                sdo.setCustomerAddressCode(array[2]);
                sdo.setCreateDate(gmtCreate);
                sdo.setTaskCountComplete(taskCountComplete);
                sdo.setBeforeMonthMoneyComplete(beforeMonthMoneyComplete);
                sdo.setMonthMoneyComplete(monthMoneyComplete);
                tmp.add(sdo);
            }
            resultMap.put(gmtCreate,tmp);
        }
        return resultMap;
    }

    //获取销售订单
    @FacadeInvoker
    private List<ObtcSaleOrderLineIndex> getAddSaleOrderDataList(JobInitParam jobInitParam){
        String beginTime = jobInitParam.getThisDay()+" 00:00:00";
        try {
            if(epochCacheService.exists(OtsApplicationReportSdkConstants.REDIS_CACHE_CODE(),REPORT_INCREMENTAL_COUNT_TIME)){
                beginTime = epochCacheService.get(OtsApplicationReportSdkConstants.REDIS_CACHE_CODE(),REPORT_INCREMENTAL_COUNT_TIME);
            }
        } catch (Exception e) {
            log.error("executeGenerateMonthSalesAddDataReport_redis_error ",e);
            return null;
        }
        String endTime = DateUtils.toDateStr(new Date(),"yyyy-MM-dd HH:mm:ss");
        log.info("executeGenerateMonthSalesAddDataReport_getAddSaleOrderDataList_queryTime=={},{}",beginTime,endTime);
        PageRecordUtil pageUtil = new PageRecordUtil();
        pageUtil.resetPageParam();
        CommPageQueryRequest queryRequest = CommPageQueryRequest.builder()
                .beginDate(beginTime)
                .endDate(endTime)
                .limit(pageUtil.getPageSize())
                .build();
        List<ObtcSaleOrderLineIndex> allData = new ArrayList<>();
        for (int i = 1; i <= pageUtil.getPage(); i++) {
            queryRequest.setStart(pageUtil.getStart());
            PageResult<List<ObtcSaleOrderLineIndex>> pageResult = salesOrderLineRepository.statisticalSalesOrderQuantityGroupByCreate(queryRequest);
            allData.addAll(pageResult.getContent());
            if(i == 1){
                pageUtil.setTotalPages(pageResult.getTotal());
            }
            pageUtil.turnPage();
        }
        epochCacheService.put(OtsApplicationReportSdkConstants.REDIS_CACHE_CODE(), REPORT_INCREMENTAL_COUNT_TIME, endTime, 100L, TimeUnit.DAYS);
        return allData;
    }

    //获取月度计划总数
    private int getSalePlanDataTotal(JobInitParam jobInitParam, String orgBusinessUnitCode){
        CommPageQueryRequest request = new CommPageQueryRequest();
        request.setPlanMonth(jobInitParam.getThisMonthTimestamp());
        request.setOrgBusinessUnitCode(orgBusinessUnitCode);
        request.setStart(0);
        request.setLimit(1);
        PageResult<List<MonthSalesPlanProgressReportSDO>> planPageResult = salesPlanDetailRepository.pageStatisticalMonthPlanProgressData(request);
        return planPageResult.getTotal();
    }

    //获取销售订单总数
    private int getSaleOrderDataTotal(JobInitParam jobInitParam, String orgSalesOrganizationCode){
        CommPageQueryRequest request = new CommPageQueryRequest();
        request.setStart(0);
        request.setLimit(1);
        request.setOrgSalesOrganizationCode(orgSalesOrganizationCode);
        request.setBeginDate(jobInitParam.getThisMonth()+"-01 00:00:00");
        request.setEndDate(jobInitParam.getThisDay()+" 23:59:59");
        Result<List<ObtcSaleOrderLineIndex>> orderPageResult = salesOrderLineRepository.statisticalMonthSalesOrderCompleteData(request);
        return orderPageResult.getTotal();
    }

    //获取送达方x货品合同总数
    private int getPlanContractDataTotal(JobInitParam jobInitParam, String orgBusinessUnitCode){
        BatchQueryContractQuantityRequest request = new BatchQueryContractQuantityRequest();
        request.setStart(0);
        request.setLimit(1);
        request.setOrgBusinessUnitCode(orgBusinessUnitCode);
        request.setContractYear(jobInitParam.getThisYear());
        Result<List<Contract>> orderPageResult = contractQuantityRepository.pageQueryContractMoney(request);
        return orderPageResult.getTotal();
    }

    //取月度销售基础报表
    private int getBasicReportTotal(String bizUnitId,String statisticalDate){
        QueryMonthSalesReportRequest queryReportRequest = new QueryMonthSalesReportRequest();
        queryReportRequest.setOrgBusinessUnitIds(Arrays.asList(bizUnitId));
        queryReportRequest.setStatisticalDate(statisticalDate);
        queryReportRequest.setStart(0);
        queryReportRequest.setLimit(1);
        PageResult<List<MonthSalesBasicReportSDO>> pageResult = monthSalesBasicReportQueryRepository.pageQueryList(queryReportRequest);
        return pageResult.getTotal();
    }

    public BigDecimal getContractMoney(String month, Contract contract){
        BigDecimal amount = new BigDecimal(0);
        switch (month){
            case "1" :
                amount = new BigDecimal(contract.getJanAmount());
                break;
            case "2" :
                amount = new BigDecimal(contract.getFebAmount());
                break;
            case "3" :
                amount = new BigDecimal(contract.getMarAmount());
                break;
            case "4" :
                amount = new BigDecimal(contract.getAprAmount());
                break;
            case "5" :
                amount = new BigDecimal(contract.getMayAmount());
                break;
            case "6" :
                amount = new BigDecimal(contract.getJuneAmount());
                break;
            case "7" :
                amount = new BigDecimal(contract.getJulyAmount());
                break;
            case "8" :
                amount = new BigDecimal(contract.getAugAmount());
                break;
            case "9" :
                amount = new BigDecimal(contract.getSeptAmount());
                break;
            case "10" :
                amount = new BigDecimal(contract.getOctAmount());
                break;
            case "11" :
                amount = new BigDecimal(contract.getNovAmount());
                break;
            case "12" :
                amount = new BigDecimal(contract.getDecAmount());
                break;
        }
        return amount.divide(new BigDecimal(100));
    }

    //取业务单元当天基础表数据
    private List<MonthSalesBasicReportSDO> getBasicReportList(String bizUnitId,String statisticalDate){
        List<Future<List<MonthSalesBasicReportSDO>>> futureList = Lists.newArrayList();
        int total = getBasicReportTotal(bizUnitId,statisticalDate);
        int totalPage = total/PageSize_1000;
        if (total%PageSize_1000>0){
            totalPage++;
        }
        for (int pageNo = 0; pageNo < totalPage; pageNo++) {
            int start = pageNo*PageSize_1000;
            CompletableFuture<List<MonthSalesBasicReportSDO>> future = CompletableFuture.supplyAsync(() -> {
                QueryMonthSalesReportRequest request = new QueryMonthSalesReportRequest();
                request.setOrgBusinessUnitIds(Arrays.asList(bizUnitId));
                request.setStatisticalDate(statisticalDate);
                request.setStart(start);
                request.setLimit(PageSize_1000);
                PageResult<List<MonthSalesBasicReportSDO>> respone = null;
                try {
                    respone = monthSalesBasicReportQueryRepository.pageQueryList(request);
                    if (respone==null || CollectionUtils.isEmpty(respone.getContent())){
                        return Lists.newArrayList();
                    }
                } catch (Exception e) {
                    log.error("getBasicReportList_query_error ", e);
                    return Lists.newArrayList();
                }
                return respone.getContent();
            }, contractStatTaskExecutor);
            futureList.add(future);
        }
        List<MonthSalesBasicReportSDO> result = new ArrayList<>();
        try {
            for (Future< List<MonthSalesBasicReportSDO>> future : futureList){
                List<MonthSalesBasicReportSDO> subList = future.get();
                result.addAll(subList);
            }
        }catch (Exception e){
            log.error("getBasicReportList_query_error_get_result_error ", e);
        }
        return result;
    }

    //比较旧报表数据
    private void compareOldBasicReport(String bizUnitId,String statisticalDate,List<MonthSalesBasicReportSDO> batchDeleteList,Map<String, MonthSalesBasicReportSDO> mergeMap){
        List<Future<Boolean>> futureList = Lists.newArrayList();
        int total = getBasicReportTotal(bizUnitId,statisticalDate);
        int totalPage = total/PageSize_1000;
        if (total%PageSize_1000>0){
            totalPage++;
        }
        for (int pageNo = 0; pageNo < totalPage; pageNo++) {
            int start = pageNo*PageSize_1000;
            CompletableFuture<Boolean> future = CompletableFuture.supplyAsync(() -> {
                QueryMonthSalesReportRequest request = new QueryMonthSalesReportRequest();
                request.setOrgBusinessUnitIds(Arrays.asList(bizUnitId));
                request.setStatisticalDate(statisticalDate);
                request.setStart(start);
                request.setLimit(PageSize_1000);
                PageResult<List<MonthSalesBasicReportSDO>> respone = null;
                try {
                    respone = monthSalesBasicReportQueryRepository.pageQueryList(request);
                    if (respone==null || CollectionUtils.isEmpty(respone.getContent())){
                        log.info("getBasicReportList_query_error_result_null,request={}", JSONObject.toJSON(request));
                        return false;
                    }
                } catch (Exception e) {
                    log.error("getBasicReportList_query_error ", e);
                    return false;
                }
                respone.getContent().forEach(x->{
                    MonthSalesBasicReportSDO mergeSDO = mergeMap.get(fetchKey(x));
                    if (mergeSDO == null) {
                        batchDeleteList.add(x);
                    } else {
                        if (!needUpdate(mergeSDO,x)) {
                            log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_exist_no_update_existed={}", bizUnitId, JSON.toJSONString(x));
                        } else {
                            Integer count = monthSalesBasicReportWriteRepository.update(mergeSDO);
                            log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_exist_need_update_sdo={},success_result={}", bizUnitId, JSON.toJSONString(mergeSDO), count);
                        }
                        mergeSDO.setHasProcess(true);//对应已修改数据库旧数据
                    }
                });
                return true;
            }, contractStatTaskExecutor);
            futureList.add(future);
        }
        List<Boolean> result = new ArrayList<>();
        try {
            for (Future<Boolean> future : futureList){
                Boolean sub = future.get();
                result.add(sub);
            }
        }catch (Exception e){
            log.error("getBasicReportList_query_error_get_result_error ", e);
        }
    }

    //判断是否需要更新
    private boolean needUpdate(MonthSalesBasicReportSDO todo, MonthSalesBasicReportSDO existed){
        return !todo.getTaskCount().equals(existed.getTaskCount()) || !todo.getTaskCountComplete().equals(existed.getTaskCountComplete())
                || todo.getMonthMoney().compareTo(existed.getMonthMoney())!=0 || todo.getMonthMoneyComplete().compareTo(existed.getMonthMoneyComplete())!=0
                || todo.getBeforeMonthMoney().compareTo(existed.getBeforeMonthMoney())!=0 || todo.getBeforeMonthMoneyComplete().compareTo(existed.getBeforeMonthMoneyComplete())!=0
                || todo.getContractMoney().compareTo(existed.getContractMoney())!=0;
    }

    //构建基础报表模型数据（月度计划+销售订单+合同金额）
    private List<MonthSalesBasicReportSDO> buildBasicReportList(JobInitParam jobInitParam,
                                                                List<MonthSalesPlanProgressReportSDO> planList,
                                                                List<ObtcSaleOrderLineIndex> orderList,
                                                                List<Contract> contractList,
                                                                String companyOrgId){

        List<MonthSalesBasicReportSDO> todoList = new ArrayList<>();
        List<ObtcSaleOrderLineIndex> hitOrderList = new ArrayList<>();
        List<Contract> hitContractList = new ArrayList<>();

//        StopWatch sw2 = new StopWatch();
//        sw2.start("buildBasicReportList_merge");
        for (MonthSalesPlanProgressReportSDO plan : planList){
            MonthSalesBasicReportSDO todo = addReportDataSDOConverter(plan);
            todo.setStatisticalDate(jobInitParam.getThisDay());
            todo.setDataMark(jobInitParam.getIsMonthDataMark());
            String planScItemKey = fetchKey(todo);
            //取销售订单数据
            List<ObtcSaleOrderLineIndex> lines = orderList.stream().filter(x->{
                if(fetchKey(x).equals(planScItemKey)){
                    return true;
                }else {
                    return false;
                }
            }).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(lines)){
                hitOrderList.addAll(lines);
                orderList.removeAll(lines);
                log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_buildBasicReportList_merge_find_order_list={},size={},planScItemKey={}",companyOrgId,JSON.toJSONString(lines),lines.size(),planScItemKey);
                MonthSalesOrderCompleteSDO order = buildSalesOrderCompleteSDO(lines);
                todo.setTaskCountComplete(order.getTaskCountComplete());
                todo.setBeforeMonthMoneyComplete(order.getBeforeMonthMoneyComplete());
                todo.setMonthMoneyComplete(order.getMonthMoneyComplete());
            }else{
                todo.setTaskCountComplete(0L);
                todo.setBeforeMonthMoneyComplete(new BigDecimal(0));
                todo.setMonthMoneyComplete(new BigDecimal(0));
            }
            //取合同金额数据
            List<Contract> contracts = contractList.stream().filter(x->{
                if(fetchKey(x).equals(planScItemKey)){
                    return true;
                }else {
                    return false;
                }
            }).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(contracts)){
                hitContractList.addAll(contracts);
                contractList.removeAll(contracts);
                log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_buildBasicReportList_merge_find_contract_list={},size={},planScItemKey={}",companyOrgId,JSON.toJSONString(contracts),contracts.size(),planScItemKey);
                BigDecimal contractMoney = buildContract(jobInitParam.getMonth(), contracts);
                todo.setContractMoney(contractMoney);
            }else{
                todo.setContractMoney(new BigDecimal(0));
            }
            countSalesOrderComplete(todo);
            todoList.add(todo);
        }
//        sw2.stop();

        log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_buildBasicReportList_merge_isHitSalesOrder_size={}",companyOrgId,hitOrderList.size());
//        sw2.start("buildBasicReportList_merge_no_order");
        //没有计划的销售订单处理
        //List<ObtcSaleOrderLineIndex> noHitOrderList = orderList.stream().filter(x-> !isHitSalesOrder(hitOrderList,x)).collect(Collectors.toList());
        List<ObtcSaleOrderLineIndex> noHitOrderList = orderList;
        log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_buildBasicReportList_merge_noHitOrderList_size={}",companyOrgId,noHitOrderList.size());
        Map<String,List<ObtcSaleOrderLineIndex>> noHitOrderMap = noHitOrderList.stream().collect(Collectors.groupingBy(x->fetchKey(x)));
        for (Map.Entry<String,List<ObtcSaleOrderLineIndex>> m2 : noHitOrderMap.entrySet()) {
            List<ObtcSaleOrderLineIndex> list = m2.getValue();
            log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_buildBasicReportList_merge_find_order2_list={},size={},planScItemKey={}",companyOrgId,JSON.toJSONString(list),list.size(),m2.getKey());
            MonthSalesBasicReportSDO sdo = buildMonthSalesBasicReportSDO(list);
            sdo.setPlanTime(jobInitParam.getThisMonthTimestamp());
            sdo.setStatisticalDate(jobInitParam.getThisDay());
            sdo.setDataMark(jobInitParam.getIsMonthDataMark());
            //取合同金额数据
            List<Contract> contracts2 = contractList.stream().filter(x->{
                if(fetchKey(x).equals(fetchKey(sdo))){
                    return true;
                }else {
                    return false;
                }
            }).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(contracts2)){
                hitContractList.addAll(contracts2);
                contractList.removeAll(contracts2);
                log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_buildBasicReportList_merge_find_contract2_list={},size={},planScItemKey={}",companyOrgId,JSON.toJSONString(contracts2),contracts2.size(),m2.getKey());
                BigDecimal contractMoney = buildContract(jobInitParam.getMonth(), contracts2);
                sdo.setContractMoney(contractMoney);
            }else{
                sdo.setContractMoney(new BigDecimal(0));
            }
            countSalesOrderComplete(sdo);
            todoList.add(sdo);
        }
//        sw2.stop();

        log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_buildBasicReportList_merge_isHitContract_size={}",companyOrgId,hitContractList.size());
//        sw2.start("buildBasicReportList_merge_no_order_no_contract");
        //没有计划、没有销售单的客户合同处理
        //List<Contract> noHitContractList = contractList.stream().filter(x-> !hitContractList.contains(x)).collect(Collectors.toList());
        List<Contract> noHitContractList = contractList;
        log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_buildBasicReportList_merge_noHitContractList_size={}",companyOrgId,noHitContractList.size());
        Map<String,List<Contract>> noHitContractMap = noHitContractList.stream().collect(Collectors.groupingBy(x->fetchKey(x)));
        for (Map.Entry<String,List<Contract>> m2 : noHitContractMap.entrySet()) {
            List<Contract> list = m2.getValue();
            log.info("salesReportSubtask{}=executeGenerateMonthSalesBasicReport_future_buildBasicReportList_merge_find_contract3_list={},size={},planScItemKey={}",companyOrgId,JSON.toJSONString(list),list.size(),m2.getKey());
            MonthSalesBasicReportSDO sdo = buildMonthSalesBasicReportSDO2(list);
            sdo.setPlanTime(jobInitParam.getThisMonthTimestamp());
            sdo.setStatisticalDate(jobInitParam.getThisDay());
            sdo.setDataMark(jobInitParam.getIsMonthDataMark());
            BigDecimal contractMoney = buildContract(jobInitParam.getMonth(), list);
            sdo.setContractMoney(contractMoney);
            countSalesOrderComplete(sdo);
            todoList.add(sdo);
        }

//        sw2.stop();
//        log.info("executeGenerateMonthSalesBasicReport_buildBasicReportList_stopWatch={}", sw2.prettyPrint());

//        List<ObtcSaleOrderLineIndex> convertList = noHitOrderList.stream().map(x ->{
//            ObtcSaleOrderLineIndex index = new ObtcSaleOrderLineIndex();
//            index.setSubMainOrderId(x.getSubMainOrderId());
//            index.setSubId(x.getSubId());
//            index.setSubScItemOutCode(x.getSubScItemOutCode());
//            index.setMainCustomerCode(x.getMainCustomerCode());
//            index.setMainReceiveAddressCode(x.getMainReceiveAddressCode());
//            index.setSubDeliveryAmount(x.getSubDeliveryAmount());
//            return index;
//        }).collect(Collectors.toList());
//        log.info("executeGenerateMonthSalesBasicReport_noHit_orderList_size={},{}",convertList.size(),JSON.toJSON(convertList));
        return todoList;
    }

    private boolean isHitSalesOrder(List<ObtcSaleOrderLineIndex> hitOrderList,ObtcSaleOrderLineIndex order){
        boolean b = false;
        for(ObtcSaleOrderLineIndex line:hitOrderList){
            if(fetchKey(order).equals(fetchKey(line))){
                b = true;
                break;
            }
        }
        return b;
    }

    private boolean isFullAndDistinct(MonthSalesBasicReportSDO sdo, Set<String> keySet){
        if (StringUtils.isBlank(sdo.getScItemCode())
                || StringUtils.isBlank(sdo.getCustomerCode())
                || StringUtils.isBlank(sdo.getCustomerAddressCode())){
            log.info("MonthSalesBasicReportSDO_core_data_not_full,sdo={}",JSON.toJSONString(sdo));
            return false;
        }
        String key = fetchKey(sdo);
        if (keySet.contains(key)){
            log.info("MonthSalesBasicReportSDO_core_data_double,sdo={}", JSON.toJSONString(sdo));
            return false;
        }else {
            keySet.add(key);
            return true;
        }
    }

    private MonthSalesOrderCompleteSDO buildSalesOrderCompleteSDO(List<ObtcSaleOrderLineIndex> lines){
        MonthSalesOrderCompleteSDO sdo = new MonthSalesOrderCompleteSDO();
        try {
            BigDecimal taskCount = new BigDecimal(0);
            BigDecimal beforeMonthMoneyComplete = new BigDecimal(0);
            BigDecimal monthMoneyComplete = new BigDecimal(0);
            for (int i=0; i<lines.size(); i++){
                ObtcSaleOrderLineIndex line = lines.get(i);
                BigDecimal amount = new BigDecimal(0);
                BigDecimal beforeAmount = new BigDecimal(0);
                BigDecimal invoiceZk01 = new BigDecimal(0);
                if (StringUtils.isNotBlank(line.getSubDeliveryAmount())) {
                    amount = new BigDecimal(line.getSubDeliveryAmount());
                }
                if (StringUtils.isNotBlank(line.getSubDctBeforePrice())) {
                    beforeAmount = new BigDecimal(line.getSubDctBeforePrice()).multiply(amount).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                }
                if (StringUtils.isNotBlank(line.getSubInvoiceZK01())) {
                    invoiceZk01 = new BigDecimal(line.getSubInvoiceZK01()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                }

                //标准退货订单
                if(SaleOrderTag.STD_RETURN_ORDER.getCode().equals(line.getMainOrderType())) {
                    taskCount = taskCount.subtract(amount);
                    beforeMonthMoneyComplete = beforeMonthMoneyComplete.subtract(beforeAmount);
                    monthMoneyComplete = monthMoneyComplete.subtract(invoiceZk01);
                    //标准订单，车销订单，现金订单
                }else{
                    taskCount = taskCount.add(amount);
                    beforeMonthMoneyComplete = beforeMonthMoneyComplete.add(beforeAmount);
                    monthMoneyComplete = monthMoneyComplete.add(invoiceZk01);
                }
            }
            sdo.setTaskCountComplete(taskCount.longValue());
            sdo.setBeforeMonthMoneyComplete(beforeMonthMoneyComplete);
            sdo.setMonthMoneyComplete(monthMoneyComplete);
            return sdo;
        }catch (Exception e){
            sdo.setTaskCountComplete(0L);
            sdo.setBeforeMonthMoneyComplete(new BigDecimal(0));
            sdo.setMonthMoneyComplete(new BigDecimal(0));
            log.error("buildSalesOrderCompleteSDO_error ", e);
            return sdo;
        }
    }

    private MonthSalesBasicReportSDO buildMonthSalesBasicReportSDO(List<ObtcSaleOrderLineIndex> lines){
        MonthSalesBasicReportSDO sdo = new MonthSalesBasicReportSDO();
        ObtcSaleOrderLineIndex tmp = lines.get(0);
        sdo.setOrgBusinessUnitId(tmp.getMainBisUnitCode());
        sdo.setOrgSalesOrganizationId(tmp.getMainOrganizationCode());
        sdo.setOrgSalesChannelId(StringUtils.isNotBlank(tmp.getMainSaleChannelCode())?tmp.getMainSaleChannelCode():"000"+sdo.getOrgSalesOrganizationId());
        sdo.setOrgSalesDepartmentId(StringUtils.isNotBlank(tmp.getMainDepartmentCode())?tmp.getMainDepartmentCode():"000"+sdo.getOrgSalesChannelId());
        sdo.setManageEmployeeId(tmp.getMainSalesmanId());
        sdo.setCustomerCode(tmp.getMainCustomerCode());
        sdo.setCustomerAddressCode(tmp.getMainReceiveAddressCode());
        sdo.setScItemCode(tmp.getSubScItemId());
        sdo.setTaskCount(0L);
        sdo.setBeforeMonthMoney(new BigDecimal(0));
        sdo.setMonthMoney(new BigDecimal(0));
        MonthSalesOrderCompleteSDO order = buildSalesOrderCompleteSDO(lines);
        sdo.setTaskCountComplete(order.getTaskCountComplete());
        sdo.setBeforeMonthMoneyComplete(order.getBeforeMonthMoneyComplete());
        sdo.setMonthMoneyComplete(order.getMonthMoneyComplete());
        return sdo;
    }

    private MonthSalesBasicReportSDO buildMonthSalesBasicReportSDO2(List<Contract> lines){
        MonthSalesBasicReportSDO sdo = new MonthSalesBasicReportSDO();
        Contract tmp = lines.get(0);
        sdo.setOrgBusinessUnitId(tmp.getOrgBusinessUnitCode());
        sdo.setOrgSalesOrganizationId(tmp.getOrgSalesOrganizationCode());
        sdo.setOrgSalesChannelId(StringUtils.isNotBlank(tmp.getOrgSalesChannelCode())?tmp.getOrgSalesChannelCode():"000"+sdo.getOrgSalesOrganizationId());
        sdo.setOrgSalesDepartmentId(StringUtils.isNotBlank(tmp.getOrgSalesDepartmentCode())?tmp.getOrgSalesDepartmentCode():"000"+sdo.getOrgSalesChannelId());
        sdo.setManageEmployeeId(tmp.getManageEmployeeId());
        sdo.setCustomerCode(tmp.getCustomerCode());
        sdo.setCustomerAddressCode(tmp.getCustomerAddress());
        sdo.setScItemCode(tmp.getScItemId());
        sdo.setTaskCount(0L);
        sdo.setBeforeMonthMoney(new BigDecimal(0));
        sdo.setMonthMoney(new BigDecimal(0));
        sdo.setTaskCountComplete(0L);
        sdo.setBeforeMonthMoneyComplete(new BigDecimal(0));
        sdo.setMonthMoneyComplete(new BigDecimal(0));
        return sdo;
    }

    private BigDecimal buildContract(String month, List<Contract> contracts){
        BigDecimal contractMoney = new BigDecimal(0);
        for (int i=0; i<contracts.size(); i++){
            Contract contract = contracts.get(i);
            contractMoney = contractMoney.add(getContractMoney(month, contract));
        }
        return contractMoney;
    }

    private void resetCountOrder(MonthSalesBasicReportSDO sdo, MonthSalesOrderCompleteSDO addOrder){
        //任务量
        BigDecimal taskCount = new BigDecimal(sdo.getTaskCount());
        //折前任务金额
        BigDecimal beforeMonthMoney = sdo.getBeforeMonthMoney().setScale(2, BigDecimal.ROUND_HALF_UP);;
        //折后任务金额
        BigDecimal monthMoney = sdo.getMonthMoney().setScale(2, BigDecimal.ROUND_HALF_UP);
        //折后合同金额
        BigDecimal contractMoney = sdo.getContractMoney().setScale(2, BigDecimal.ROUND_HALF_UP);
        //任务达成量
        BigDecimal taskCountComplete  = new BigDecimal(sdo.getTaskCountComplete()+addOrder.getTaskCountComplete());
        sdo.setTaskCountComplete(taskCountComplete.longValue());
        //折前任务金额达成量
        BigDecimal beforeMonthMoneyComplete = sdo.getBeforeMonthMoneyComplete().add(addOrder.getBeforeMonthMoneyComplete());
        sdo.setBeforeMonthMoneyComplete(beforeMonthMoneyComplete);
        //折后任务金额达成量
        BigDecimal monthMoneyComplete = sdo.getMonthMoneyComplete().add(addOrder.getMonthMoneyComplete());
        sdo.setMonthMoneyComplete(monthMoneyComplete);
        sdo.setContractMoneyComplete(monthMoneyComplete);
        //任务达成量百分比
        BigDecimal taskCountCompletePercentage = taskCount.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):taskCountComplete.divide(taskCount,4,BigDecimal.ROUND_HALF_UP);
        sdo.setTaskCountCompletePercentage(taskCountCompletePercentage);
        //折前任务金额达成百分比
        BigDecimal beforeMonthMoneyCompletePercentage = beforeMonthMoney.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):beforeMonthMoneyComplete.divide(beforeMonthMoney,4,BigDecimal.ROUND_HALF_UP);
        sdo.setBeforeMonthMoneyCompletePercentage(beforeMonthMoneyCompletePercentage);
        //折后任务金额达成百分比
        BigDecimal monthMoneyCompletePercentage = monthMoney.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):monthMoneyComplete.divide(monthMoney,4,BigDecimal.ROUND_HALF_UP);
        sdo.setMonthMoneyCompletePercentage(monthMoneyCompletePercentage);
        //折后合同金额达成百分比
        BigDecimal contractMoneyCompletePercentage = contractMoney.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):monthMoneyComplete.divide(contractMoney,4,BigDecimal.ROUND_HALF_UP);
        sdo.setContractMoneyCompletePercentage(contractMoneyCompletePercentage);
        //任务差量
        BigDecimal taskCountRemain = taskCountComplete.subtract(taskCount);
        sdo.setTaskCountRemain(taskCountRemain.longValue());
        //折前任务差额
        BigDecimal beforeMonthMoneyRemain = beforeMonthMoneyComplete.subtract(beforeMonthMoney);
        sdo.setBeforeMonthMoneyRemain(beforeMonthMoneyRemain);
        //折后任务差额
        BigDecimal monthMoneyRemain = monthMoneyComplete.subtract(monthMoney);
        sdo.setMonthMoneyRemain(monthMoneyRemain);
        //折后合同差额
        BigDecimal contractMoneyRemain = monthMoneyComplete.subtract(contractMoney);
        sdo.setContractMoneyRemain(contractMoneyRemain);
    }

    private MonthSalesBasicReportSDO resetCountCreateReport(MonthSalesOrderCompleteSDO addOrder){
        MonthSalesBasicReportSDO sdo = new MonthSalesBasicReportSDO();
        sdo.setOrgBusinessUnitId(addOrder.getOrgBusinessUnitCode());
        sdo.setOrgSalesOrganizationId(addOrder.getOrgSalesOrganizationCode());
        sdo.setOrgSalesChannelId(addOrder.getOrgSalesChannelCode());
        sdo.setOrgSalesDepartmentId(addOrder.getOrgSalesDepartmentCode());
        sdo.setCustomerCode(addOrder.getCustomerCode());
        sdo.setCustomerAddressCode(addOrder.getCustomerAddressCode());
        sdo.setScItemCode(addOrder.getScItemId());
        sdo.setManageEmployeeId(addOrder.getManageEmployeeId());
        sdo.setStatisticalDate(addOrder.getCreateDate());
        Date statisticalDate = DateUtils.parse(sdo.getStatisticalDate());
        sdo.setPlanTime(DomUtil.getMonthTimestamp(statisticalDate));
        sdo.setDataMark(DomUtil.isLastDayOfMonth(statisticalDate)? DataMarkEnum.MONTH_FINAL_DATA.getCode():DataMarkEnum.MONTH_ACCUM_DATA.getCode());

        //任务量
        BigDecimal taskCount = new BigDecimal(0);
        //折前任务金额
        BigDecimal beforeMonthMoney = new BigDecimal(0);
        //折后任务金额
        BigDecimal monthMoney = new BigDecimal(0);
        //折后合同金额
        BigDecimal contractMoney = new BigDecimal(0);

        //查询计划
        CommPageQueryRequest planQueryRequest = new CommPageQueryRequest();
        planQueryRequest.setPlanMonth(DomUtil.getMonthTimestamp(statisticalDate));
        planQueryRequest.setCustomerAddressCode(addOrder.getCustomerAddressCode());
        planQueryRequest.setCustomerCode(addOrder.getCustomerCode());
        planQueryRequest.setScItemId(addOrder.getScItemId());
        planQueryRequest.setStart(0);
        planQueryRequest.setLimit(100);
        PageResult<List<MonthSalesPlanProgressReportSDO>> planPageResult = salesPlanDetailRepository.pageStatisticalMonthPlanProgressData(planQueryRequest);
        log.info("executeGenerateMonthSalesAddDataReport_basic_history_create_planPageResult_request={},result={}", JSON.toJSONString(planQueryRequest),JSON.toJSONString(planPageResult.getContent()));
        if(planPageResult != null && CollectionUtils.isNotEmpty(planPageResult.getContent())){
            taskCount = new BigDecimal(planPageResult.getContent().get(0).getTaskCount());
            beforeMonthMoney = planPageResult.getContent().get(0).getBeforeMonthMoney();
            monthMoney = planPageResult.getContent().get(0).getMonthMoney();
        }

        //查询合同
        BatchQueryContractQuantityRequest contractQueryRequest = new BatchQueryContractQuantityRequest();
        contractQueryRequest.setContractYear(DomUtil.getYear(statisticalDate));
        contractQueryRequest.setCustomerAddressCode(addOrder.getCustomerAddressCode());
        contractQueryRequest.setCustomerCode(addOrder.getCustomerCode());
        contractQueryRequest.setScItemId(addOrder.getScItemId());
        contractQueryRequest.setStart(0);
        contractQueryRequest.setLimit(100);
        Result<List<Contract>> contractPageResult = contractQuantityRepository.pageQueryContractMoney(contractQueryRequest);
        log.info("executeGenerateMonthSalesAddDataReport_basic_history_create_contractPageResult_request={},result={}", JSON.toJSONString(contractQueryRequest),JSON.toJSONString(contractPageResult.getResult()));
        if(contractPageResult != null && CollectionUtils.isNotEmpty(contractPageResult.getResult())){
            Calendar cal = Calendar.getInstance();
            cal.setTime(statisticalDate);
            int month = cal.get(Calendar.MONTH) + 1;
            contractMoney = getContractMoney(String.valueOf(month), contractPageResult.getResult().get(0));
        }

        sdo.setTaskCount(taskCount.longValue());
        sdo.setBeforeMonthMoney(beforeMonthMoney);
        sdo.setMonthMoney(monthMoney);
        sdo.setContractMoney(contractMoney);
        //任务达成量
        BigDecimal taskCountComplete  = new BigDecimal(addOrder.getTaskCountComplete());
        sdo.setTaskCountComplete(taskCountComplete.longValue());
        //折前任务金额达成量
        BigDecimal beforeMonthMoneyComplete = addOrder.getBeforeMonthMoneyComplete();
        sdo.setBeforeMonthMoneyComplete(beforeMonthMoneyComplete);
        //折后任务金额达成量
        BigDecimal monthMoneyComplete = addOrder.getMonthMoneyComplete();
        sdo.setMonthMoneyComplete(monthMoneyComplete);
        sdo.setContractMoneyComplete(monthMoneyComplete);
        //任务达成量百分比
        BigDecimal taskCountCompletePercentage = taskCount.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):taskCountComplete.divide(taskCount,4,BigDecimal.ROUND_HALF_UP);
        sdo.setTaskCountCompletePercentage(taskCountCompletePercentage);
        //折前任务金额达成百分比
        BigDecimal beforeMonthMoneyCompletePercentage = beforeMonthMoney.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):beforeMonthMoneyComplete.divide(beforeMonthMoney,4,BigDecimal.ROUND_HALF_UP);
        sdo.setBeforeMonthMoneyCompletePercentage(beforeMonthMoneyCompletePercentage);
        //折后任务金额达成百分比
        BigDecimal monthMoneyCompletePercentage = monthMoney.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):monthMoneyComplete.divide(monthMoney,4,BigDecimal.ROUND_HALF_UP);
        sdo.setMonthMoneyCompletePercentage(monthMoneyCompletePercentage);
        //折后合同金额达成百分比
        BigDecimal contractMoneyCompletePercentage = contractMoney.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):monthMoneyComplete.divide(contractMoney,4,BigDecimal.ROUND_HALF_UP);
        sdo.setContractMoneyCompletePercentage(contractMoneyCompletePercentage);
        //任务差量
        BigDecimal taskCountRemain = taskCountComplete.subtract(taskCount);
        sdo.setTaskCountRemain(taskCountRemain.longValue());
        //折前任务差额
        BigDecimal beforeMonthMoneyRemain = beforeMonthMoneyComplete.subtract(beforeMonthMoney);
        sdo.setBeforeMonthMoneyRemain(beforeMonthMoneyRemain);
        //折后任务差额
        BigDecimal monthMoneyRemain = monthMoneyComplete.subtract(monthMoney);
        sdo.setMonthMoneyRemain(monthMoneyRemain);
        //折后合同差额
        BigDecimal contractMoneyRemain = monthMoneyComplete.subtract(contractMoney);
        sdo.setContractMoneyRemain(contractMoneyRemain);

        List<MonthSalesBasicReportSDO> list = Lists.newArrayList(sdo);
        enrichName(list);
        return list.get(0);
    }

    private String fetchKey(MonthSalesBasicReportSDO x){
        StringBuilder key = new StringBuilder();
        key.append(x.getScItemCode())
                .append("#")
                .append(x.getCustomerCode())
                .append("#")
                .append(x.getCustomerAddressCode());
//                .append("#")
//                .append(x.getManageEmployeeId());
        return key.toString();
    }

    private String fetchKey(ObtcSaleOrderLineIndex x){
        StringBuilder key = new StringBuilder();
        key.append(x.getSubScItemId())
                .append("#")
                .append(x.getMainCustomerCode())
                .append("#")
                .append(x.getMainReceiveAddressCode());
//                .append("#")
//                .append(x.getMainSalesmanId());
        return key.toString();
    }

    private String fetchKey(Contract x){
        StringBuilder key = new StringBuilder();
        key.append(x.getScItemId())
                .append("#")
                .append(x.getCustomerCode())
                .append("#")
                .append(x.getCustomerAddress());
//                .append("#")
//                .append(x.getManageEmployeeId());
        return key.toString();
    }

    private String fetchKey(MonthSalesOrderCompleteSDO x){
        StringBuilder key = new StringBuilder();
        key.append(x.getScItemId())
                .append("#")
                .append(x.getCustomerCode())
                .append("#")
                .append(x.getCustomerAddressCode());
//                .append("#")
//                .append(x.getManageEmployeeId());
        return key.toString();
    }

    @FacadeInvoker
    private CompletableFuture<Void> executeGenerateEmployeeRankReport(JobInitParam jobInitParam){
        return CompletableFuture.runAsync(() -> {
            PageRecordUtil pageUtil = new PageRecordUtil();
            pageUtil.resetPageParam();
            CommPageQueryRequest queryRequest = CommPageQueryRequest.builder()
                    .planMonth(jobInitParam.thisMonthTimestamp)
                    .statDate(jobInitParam.getThisDay())
                    .limit(pageUtil.getPageSize())
                    .build();
            List<MonthSalesBasicReportSDO> allData = new ArrayList<>();
            for (int i = 1; i <= pageUtil.getPage(); i++) {
                queryRequest.setStart(pageUtil.getStart());
                PageResult<List<MonthSalesBasicReportSDO>> pageResult = monthSalesBasicReportQueryRepository.pageStatisticalMonthSalesEmployeeRank(queryRequest);
                allData.addAll(pageResult.getContent());
                if(i == 1){
                    pageUtil.setTotalPages(pageResult.getTotal());
                }
                for(MonthSalesBasicReportSDO x:pageResult.getContent()){
                    //计算销售订单完成量
                    countSalesOrderComplete(x);
                    x.setDataMark(jobInitParam.getIsMonthDataMark());
//                    x.setTaskCountCompleteRankNo(Objects.equal(pageUtil.getLastTaskCountCompletePercentage(),x.getTaskCountCompletePercentage())?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
//                    pageUtil.recordTaskCountCompletePercentage(x.getTaskCountCompletePercentage());
//                    pageUtil.sortNoIncrease();
                };
                pageUtil.turnPage();
            }
            //任务完成量排序
            allData = allData.stream().sorted((s1,s2) -> s2.getTaskCountCompletePercentage().compareTo(s1.getTaskCountCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();
            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setTaskCountCompleteRankNo(pageUtil.getLastTaskCountCompletePercentage().compareTo(allData.get(i).getTaskCountCompletePercentage())==0?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordTaskCountCompletePercentage(allData.get(i).getTaskCountCompletePercentage());
                pageUtil.sortNoIncrease();
            }
            //补全折前金额已达成排序
            allData = allData.stream().sorted((s1,s2) -> s2.getBeforeMonthMoneyCompletePercentage().compareTo(s1.getBeforeMonthMoneyCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();
            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setBeforeMonthMoneyCompleteRankNo(pageUtil.getLastMonthMoneyCompletePercentage().compareTo(allData.get(i).getBeforeMonthMoneyCompletePercentage()) == 0?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordlastMonthMoneyCompletePercentage(allData.get(i).getBeforeMonthMoneyCompletePercentage());
                pageUtil.sortNoIncrease();
            }
            //补全折后金额已达成排序
            allData = allData.stream().sorted((s1,s2) -> s2.getMonthMoneyCompletePercentage().compareTo(s1.getMonthMoneyCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();
            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setMonthMoneyCompleteRankNo(pageUtil.getLastMonthMoneyCompletePercentage().compareTo(allData.get(i).getMonthMoneyCompletePercentage()) == 0?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordlastMonthMoneyCompletePercentage(allData.get(i).getMonthMoneyCompletePercentage());
                pageUtil.sortNoIncrease();
            }
            //补全折后合同金额已达成排序
            allData = allData.stream().sorted((s1,s2) -> s2.getContractMoneyCompletePercentage().compareTo(s1.getContractMoneyCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();

            //获取报表原数据
            List<MonthSalesBasicReportSDO> oldReportList = jobInitParam.getIsFirstSyncEmployeeRank()?new ArrayList<>():queryOldReport(jobInitParam.getThisDay(),EMPLOYEE_RANK);
            Map<String,MonthSalesBasicReportSDO> reportMap = Nullable.stream(oldReportList).collect(Collectors.toMap(x->x.getOrgSalesChannelId()+"#"+x.getOrgSalesDepartmentId()+"#"+x.getManageEmployeeId(), Function.identity(),(v1,v2)->v1));

            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setContractMoneyCompleteRankNo(pageUtil.getLastMonthMoneyCompletePercentage().compareTo(allData.get(i).getContractMoneyCompletePercentage()) == 0?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordlastMonthMoneyCompletePercentage(allData.get(i).getContractMoneyCompletePercentage());
                pageUtil.sortNoIncrease();

                if(jobInitParam.getIsFirstSyncEmployeeRank()){
                    String id = monthSalesEmployeeBankReportWriteRepository.add(allData.get(i));
                    log.info("<员工排名报表>新增员工计划任务完成量排名,id=={},{}",id,JSON.toJSONString(allData.get(i)));
                }else{
                    MonthSalesBasicReportSDO x = allData.get(i);
                    Map<String,Object> res = getAction(allData.get(i),reportMap.get(x.getOrgSalesChannelId()+"#"+x.getOrgSalesDepartmentId()+"#"+x.getManageEmployeeId()),EMPLOYEE_RANK);
                    log.info("<员工排名报表>计算数据完成后判断行动点结果,action={},old={},new={}",res.get("action"),JSON.toJSON(res.get("oldData")),allData.get(i));
                    if("add".equals(res.get("action"))){
                        String id = monthSalesEmployeeBankReportWriteRepository.add(allData.get(i));
                        log.info("<员工排名报表>新增员工计划任务完成量排名2,id=={},{}",id,JSON.toJSONString(allData.get(i)));
                    }else if("update".equals(res.get("action"))){
                        int count = monthSalesEmployeeBankReportWriteRepository.update(allData.get(i));
                        log.info("<员工排名报表>更新员工计划任务完成量排名,更新了{}条数据,{}",count,JSON.toJSONString(allData.get(i)));
                    }
                }
            }
            log.info("executeGenerateEmployeeRankReport_job_finish!");
        }, monthSalesReportTaskExecutor);
    }

    @FacadeInvoker
    private CompletableFuture<Void> executeGenerateDepartmentRankReport(JobInitParam jobInitParam){
        return CompletableFuture.runAsync(() -> {
            PageRecordUtil pageUtil = new PageRecordUtil();
            pageUtil.resetPageParam();
            CommPageQueryRequest queryRequest = CommPageQueryRequest.builder()
                    .planMonth(jobInitParam.thisMonthTimestamp)
                    .statDate(jobInitParam.getThisDay())
                    .limit(pageUtil.getPageSize())
                    .build();
            List<MonthSalesBasicReportSDO> allData = new ArrayList<>();
            for (int i = 1; i <= pageUtil.getPage(); i++) {
                queryRequest.setStart(pageUtil.getStart());
                PageResult<List<MonthSalesBasicReportSDO>> pageResult = monthSalesBasicReportQueryRepository.pageStatisticalMonthSalesDepartmentRank(queryRequest);
                allData.addAll(pageResult.getContent());
                if(i == 1){
                    pageUtil.setTotalPages(pageResult.getTotal());
                }
                for(MonthSalesBasicReportSDO x:pageResult.getContent()){
                    //计算销售订单完成量
                    countSalesOrderComplete(x);
                    x.setDataMark(jobInitParam.getIsMonthDataMark());
//                    x.setTaskCountCompleteRankNo(Objects.equal(pageUtil.getLastTaskCountCompletePercentage(),x.getTaskCountCompletePercentage())?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
//                    pageUtil.recordTaskCountCompletePercentage(x.getTaskCountCompletePercentage());
//                    pageUtil.sortNoIncrease();
                };
                pageUtil.turnPage();
            }

            //任务完成量排序
            allData = allData.stream().sorted((s1,s2) -> s2.getTaskCountCompletePercentage().compareTo(s1.getTaskCountCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();
            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setTaskCountCompleteRankNo(pageUtil.getLastTaskCountCompletePercentage().compareTo(allData.get(i).getTaskCountCompletePercentage())==0?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordTaskCountCompletePercentage(allData.get(i).getTaskCountCompletePercentage());
                pageUtil.sortNoIncrease();
            }
            //补全折前金额已达成排序
            allData = allData.stream().sorted((s1,s2) -> s2.getBeforeMonthMoneyCompletePercentage().compareTo(s1.getBeforeMonthMoneyCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();
            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setBeforeMonthMoneyCompleteRankNo(pageUtil.getLastMonthMoneyCompletePercentage().compareTo(allData.get(i).getBeforeMonthMoneyCompletePercentage()) == 0?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordlastMonthMoneyCompletePercentage(allData.get(i).getBeforeMonthMoneyCompletePercentage());
                pageUtil.sortNoIncrease();
            }
            //补全折后金额已达成排序
            allData = allData.stream().sorted((s1,s2) -> s2.getMonthMoneyCompletePercentage().compareTo(s1.getMonthMoneyCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();
            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setMonthMoneyCompleteRankNo(pageUtil.getLastMonthMoneyCompletePercentage().compareTo(allData.get(i).getMonthMoneyCompletePercentage()) == 0?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordlastMonthMoneyCompletePercentage(allData.get(i).getMonthMoneyCompletePercentage());
                pageUtil.sortNoIncrease();
            }
            //补全折后合同金额已达成排序
            allData = allData.stream().sorted((s1,s2) -> s2.getContractMoneyCompletePercentage().compareTo(s1.getContractMoneyCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();

            //获取报表原数据
            List<MonthSalesBasicReportSDO> oldReportList = jobInitParam.getIsFirstSyncDepartmentRank()?new ArrayList<>():queryOldReport(jobInitParam.getThisDay(),DEPARTMENT_RANK);
            Map<String,MonthSalesBasicReportSDO> reportMap = Nullable.stream(oldReportList).collect(Collectors.toMap(MonthSalesBasicReportSDO::getOrgSalesDepartmentId, Function.identity(),(v1,v2)->v1));

            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setContractMoneyCompleteRankNo(pageUtil.getLastMonthMoneyCompletePercentage().compareTo(allData.get(i).getContractMoneyCompletePercentage()) == 0 ? pageUtil.getLastSameSortNo() : pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordlastMonthMoneyCompletePercentage(allData.get(i).getContractMoneyCompletePercentage());
                pageUtil.sortNoIncrease();


                if (jobInitParam.getIsFirstSyncDepartmentRank()) {
                    String id = monthSalesDepartmentBankReportWriteRepository.add(allData.get(i));
                    log.info("<部门排名报表>新增部门计划任务完成量排名,id=={},{}", id, JSON.toJSONString(allData.get(i)));
                } else {
                    Map<String,Object> res = getAction(allData.get(i),reportMap.get(allData.get(i).getOrgSalesDepartmentId()),DEPARTMENT_RANK);
                    log.info("<部门排名报表>计算数据完成后判断行动点结果,action={},old={},new={}",res.get("action"),JSON.toJSON(res.get("oldData")),allData.get(i));
                    if("add".equals(res.get("action"))){
                        String id = monthSalesDepartmentBankReportWriteRepository.add(allData.get(i));
                        log.info("<部门排名报表>新增部门计划任务完成量排名2,id=={},{}",id,JSON.toJSONString(allData.get(i)));
                    }else if("update".equals(res.get("action"))){
                        int count = monthSalesDepartmentBankReportWriteRepository.update(allData.get(i));
                        log.info("<部门排名报表>更新部门计划任务完成量排名,更新了{}条数据,{}",count,JSON.toJSONString(allData.get(i)));
                    }
                }
            }
            log.info("executeGenerateDepartmentRankReport_job_finish!");
        }, monthSalesReportTaskExecutor);
    }

    @FacadeInvoker
    private CompletableFuture<Void> executeGenerateChannelRankReport(JobInitParam jobInitParam){
        return CompletableFuture.runAsync(() -> {
            PageRecordUtil pageUtil = new PageRecordUtil();
            pageUtil.resetPageParam();
            CommPageQueryRequest queryRequest = CommPageQueryRequest.builder()
                    .planMonth(jobInitParam.thisMonthTimestamp)
                    .statDate(jobInitParam.getThisDay())
                    .limit(pageUtil.getPageSize())
                    .build();
            List<MonthSalesBasicReportSDO> allData = new ArrayList<>();
            for (int i = 1; i <= pageUtil.getPage(); i++) {
                queryRequest.setStart(pageUtil.getStart());
                PageResult<List<MonthSalesBasicReportSDO>> pageResult = monthSalesBasicReportQueryRepository.pageStatisticalMonthSalesChannelRank(queryRequest);
                allData.addAll(pageResult.getContent());
                if(i == 1){
                    pageUtil.setTotalPages(pageResult.getTotal());
                }
                for(MonthSalesBasicReportSDO x:pageResult.getContent()){
                    //计算销售订单完成量
                    countSalesOrderComplete(x);
                    x.setDataMark(jobInitParam.getIsMonthDataMark());
//                    x.setTaskCountCompleteRankNo(pageUtil.getLastTaskCountCompletePercentage().compareTo(x.getTaskCountCompletePercentage()) == 0?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
//                    pageUtil.recordTaskCountCompletePercentage(x.getTaskCountCompletePercentage());
//                    pageUtil.sortNoIncrease();
                };
                pageUtil.turnPage();
            }
            //任务完成量排序
            allData = allData.stream().sorted((s1,s2) -> s2.getTaskCountCompletePercentage().compareTo(s1.getTaskCountCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();
            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setTaskCountCompleteRankNo(pageUtil.getLastTaskCountCompletePercentage().compareTo(allData.get(i).getTaskCountCompletePercentage())==0?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordTaskCountCompletePercentage(allData.get(i).getTaskCountCompletePercentage());
                pageUtil.sortNoIncrease();
            }
            //补全折前金额已达成排序
            allData = allData.stream().sorted((s1,s2) -> s2.getBeforeMonthMoneyCompletePercentage().compareTo(s1.getBeforeMonthMoneyCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();
            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setBeforeMonthMoneyCompleteRankNo(pageUtil.getLastMonthMoneyCompletePercentage().compareTo(allData.get(i).getBeforeMonthMoneyCompletePercentage()) == 0?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordlastMonthMoneyCompletePercentage(allData.get(i).getBeforeMonthMoneyCompletePercentage());
                pageUtil.sortNoIncrease();
            }
            //补全折后金额已达成排序
            allData = allData.stream().sorted((s1,s2) -> s2.getMonthMoneyCompletePercentage().compareTo(s1.getMonthMoneyCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();
            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setMonthMoneyCompleteRankNo(pageUtil.getLastMonthMoneyCompletePercentage().compareTo(allData.get(i).getMonthMoneyCompletePercentage()) == 0?pageUtil.getLastSameSortNo():pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordlastMonthMoneyCompletePercentage(allData.get(i).getMonthMoneyCompletePercentage());
                pageUtil.sortNoIncrease();
            }
            //补全折后合同金额已达成排序
            allData = allData.stream().sorted((s1,s2) -> s2.getContractMoneyCompletePercentage().compareTo(s1.getContractMoneyCompletePercentage())).collect(Collectors.toList());
            pageUtil.resetPageParam();

            //获取报表原数据
            List<MonthSalesBasicReportSDO> oldReportList = jobInitParam.getIsFirstSyncChannelRank()?new ArrayList<>():queryOldReport(jobInitParam.getThisDay(),CHANNEL_RANK);
            Map<String,MonthSalesBasicReportSDO> reportMap = Nullable.stream(oldReportList).collect(Collectors.toMap(MonthSalesBasicReportSDO::getOrgSalesChannelId, Function.identity(),(v1,v2)->v1));

            for (int i = 0; i < allData.size(); i++) {
                allData.get(i).setContractMoneyCompleteRankNo(pageUtil.getLastMonthMoneyCompletePercentage().compareTo(allData.get(i).getContractMoneyCompletePercentage()) == 0 ? pageUtil.getLastSameSortNo() : pageUtil.getNewSortNoAndRecordLastSortNo());
                pageUtil.recordlastMonthMoneyCompletePercentage(allData.get(i).getContractMoneyCompletePercentage());
                pageUtil.sortNoIncrease();

                if(jobInitParam.getIsFirstSyncChannelRank()){
                    String id = monthSalesChannelBankReportWriteRepository.add(allData.get(i));
                    log.info("<渠道排名报表>新增渠道计划任务完成量排名,id=={},{}",id,JSON.toJSONString(allData.get(i)));
                }else{
                    Map<String,Object> res = getAction(allData.get(i),reportMap.get(allData.get(i).getOrgSalesChannelId()),CHANNEL_RANK);
                    log.info("<渠道排名报表>计算数据完成后判断行动点结果,action={},old={},new={}",res.get("action"),JSON.toJSON(res.get("oldData")),allData.get(i));
                    if("add".equals(res.get("action"))){
                        String id = monthSalesChannelBankReportWriteRepository.add(allData.get(i));
                        log.info("<渠道排名报表>新增渠道计划任务完成量排名2,id=={},{}",id,JSON.toJSONString(allData.get(i)));
                    }else if("update".equals(res.get("action"))){
                        int count = monthSalesChannelBankReportWriteRepository.update(allData.get(i));
                        log.info("<渠道排名报表>更新渠道计划任务完成量排名,更新了{}条数据,{}",count,JSON.toJSONString(allData.get(i)));
                    }
                }
            }
            log.info("executeGenerateChannelRankReport_job_finish!");
        }, monthSalesReportTaskExecutor);
    }

    @FacadeInvoker
    private CompletableFuture<Void> executeGenerateOneCategoryReport(JobInitParam jobInitParam){
        return CompletableFuture.runAsync(() -> {
            PageRecordUtil pageUtil = new PageRecordUtil();
            pageUtil.resetPageParam();
            CommPageQueryRequest queryRequest = CommPageQueryRequest.builder()
                    .planMonth(jobInitParam.thisMonthTimestamp)
                    .statDate(jobInitParam.getThisDay())
                    .limit(pageUtil.getPageSize())
                    .build();
            //一级类目统计
            queryRequest.setBizType(BizTypeEnum.ONE_CATEGORY.getCode());

            //获取报表原数据
            List<MonthSalesBasicReportSDO> oldReportList = jobInitParam.getIsFirstSyncCategoryReport()?new ArrayList<>():queryOldReport(jobInitParam.getThisDay(),ONE_CATEGORY);
            Map<String,MonthSalesBasicReportSDO> reportMap = Nullable.stream(oldReportList).collect(Collectors.toMap(x->x.getOrgSalesChannelId()+"#"+x.getOrgSalesDepartmentId()+"#"+x.getScItemCategoryId(), Function.identity(),(v1,v2)->v1));

            for (int i = 1; i <= pageUtil.getPage(); i++) {
                queryRequest.setStart(pageUtil.getStart());
                PageResult<List<MonthSalesBasicReportSDO>> pageResult = monthSalesBasicReportQueryRepository.pageStatisticalMonthSalesCategory(queryRequest);
                if(i == 1){
                    pageUtil.setTotalPages(pageResult.getTotal());
                }
                for(MonthSalesBasicReportSDO x:pageResult.getContent()){
                    //计算销售订单完成量
                    countSalesOrderComplete(x);
                    x.setBizType(BizTypeEnum.ONE_CATEGORY.getCode());
                    x.setDataMark(jobInitParam.getIsMonthDataMark());
                    if(jobInitParam.getIsFirstSyncCategoryReport()){
                        String id = monthSalesCategoryReportWriteRepository.add(x);
                        log.info("<部门一级类目报表>新增部门一级类目报表,id=={},{}",id,JSON.toJSONString(x));
                    }else{
                        Map<String,Object> res = getAction(x,reportMap.get(x.getOrgSalesChannelId()+"#"+x.getOrgSalesDepartmentId()+"#"+x.getScItemCategoryId()),CATEGORY);
                        log.info("<部门一级类目报表>计算数据完成后判断行动点结果,action={},old={},new={}",res.get("action"),JSON.toJSON(res.get("oldData")),x);
                        if("add".equals(res.get("action"))){
                            String id = monthSalesCategoryReportWriteRepository.add(x);
                            log.info("<部门一级类目报表>新增部门一级类目报表2,id=={},{}",id,JSON.toJSONString(x));
                        }else if("update".equals(res.get("action"))){
                            int count = monthSalesCategoryReportWriteRepository.update(x);
                            log.info("<部门一级类目报表>更新部门一级类目报表,更新了{}条数据,{}",count,JSON.toJSONString(x));
                        }
                    }
                    pageUtil.sortNoIncrease();
                };
                pageUtil.turnPage();
            }
            log.info("executeGenerateOneCategoryReport_job_finish!");
        }, monthSalesReportTaskExecutor);
    }

    @FacadeInvoker
    private CompletableFuture<Void> executeGenerateTwoCategoryReport(JobInitParam jobInitParam){
        return CompletableFuture.runAsync(() -> {
            PageRecordUtil pageUtil = new PageRecordUtil();
            pageUtil.resetPageParam();
            CommPageQueryRequest queryRequest = CommPageQueryRequest.builder()
                    .planMonth(jobInitParam.thisMonthTimestamp)
                    .statDate(jobInitParam.getThisDay())
                    .limit(pageUtil.getPageSize())
                    .build();
            //二级类目统计
            queryRequest.setBizType(BizTypeEnum.TWO_CATEGORY.getCode());

            //获取报表原数据
            List<MonthSalesBasicReportSDO> oldReportList = jobInitParam.getIsFirstSyncCategoryReport()?new ArrayList<>():queryOldReport(jobInitParam.getThisDay(),TWO_CATEGORY);
            Map<String,MonthSalesBasicReportSDO> reportMap = Nullable.stream(oldReportList).collect(Collectors.toMap(x->x.getOrgSalesChannelId()+"#"+x.getOrgSalesDepartmentId()+"#"+x.getScItemCategoryId(), Function.identity(),(v1,v2)->v1));

            for (int i = 1; i <= pageUtil.getPage(); i++) {
                queryRequest.setStart(pageUtil.getStart());
                PageResult<List<MonthSalesBasicReportSDO>> pageResult = monthSalesBasicReportQueryRepository.pageStatisticalMonthSalesCategory(queryRequest);
                if(i == 1){
                    pageUtil.setTotalPages(pageResult.getTotal());
                }
                for(MonthSalesBasicReportSDO x:pageResult.getContent()){
                    //计算销售订单完成量
                    countSalesOrderComplete(x);
                    x.setBizType(BizTypeEnum.TWO_CATEGORY.getCode());
                    x.setDataMark(jobInitParam.getIsMonthDataMark());
                    if(jobInitParam.getIsFirstSyncCategoryReport()){
                        String id = monthSalesCategoryReportWriteRepository.add(x);
                        log.info("<部门二级类目报表>新增部门二级类目报表,id=={},{}",id,JSON.toJSONString(x));
                    }else{
                        Map<String,Object> res = getAction(x,reportMap.get(x.getOrgSalesChannelId()+"#"+x.getOrgSalesDepartmentId()+"#"+x.getScItemCategoryId()),CATEGORY);
                        log.info("<部门二级类目报表>计算数据完成后判断行动点结果,action={},old={},new={}",res.get("action"),JSON.toJSON(res.get("oldData")),x);
                        if("add".equals(res.get("action"))){
                            String id = monthSalesCategoryReportWriteRepository.add(x);
                            log.info("<部门二级类目报表>新增部门二级类目报表2,id=={},{}",id,JSON.toJSONString(x));
                        }else if("update".equals(res.get("action"))){
                            int count = monthSalesCategoryReportWriteRepository.update(x);
                            log.info("<部门二级类目报表>更新部门二级类目报表,更新了{}条数据,{}",count,JSON.toJSONString(x));
                        }
                    }
                    pageUtil.sortNoIncrease();
                };
                pageUtil.turnPage();
            }
            log.info("executeGenerateTwoCategoryReport_job_finish!");
        }, monthSalesReportTaskExecutor);
    }

//    @FacadeInvoker
//    private CompletableFuture<Void> executeGenerateCompanyOneCategoryReport(JobInitParam jobInitParam){
//        return CompletableFuture.runAsync(() -> {
//            PageRecordUtil pageUtil = new PageRecordUtil();
//            pageUtil.resetPageParam();
//            CommPageQueryRequest queryRequest = CommPageQueryRequest.builder()
//                    .planMonth(jobInitParam.thisMonthTimestamp)
//                    .statDate(jobInitParam.getThisDay())
//                    .limit(pageUtil.getPageSize())
//                    .build();
//            //一级类目统计
//            queryRequest.setBizType(BizTypeEnum.ONE_CATEGORY.getCode());
//
//            //获取报表原数据
//            List<MonthSalesBasicReportSDO> oldReportList = jobInitParam.getIsFirstSyncEmployeeRank()?new ArrayList<>():queryOldReport(jobInitParam.getThisDay(),ONE_CATEGORY);
//            Map<String,MonthSalesBasicReportSDO> reportMap = Nullable.stream(oldReportList).collect(Collectors.toMap(MonthSalesBasicReportSDO::getManageEmployeeId, Function.identity(),(v1,v2)->v1));
//
//            for (int i = 1; i <= pageUtil.getPage(); i++) {
//                queryRequest.setStart(pageUtil.getStart());
//                PageResult<List<MonthSalesBasicReportSDO>> pageResult = monthSalesBasicReportQueryRepository.pageStatisticalMonthSalesCategory(queryRequest);
//                if(i == 1){
//                    pageUtil.setTotalPages(pageResult.getTotal());
//                }
//                for(MonthSalesBasicReportSDO x:pageResult.getContent()){
//                    //计算销售订单完成量
//                    countSalesOrderComplete(x);
//                    x.setBizType(BizTypeEnum.ONE_CATEGORY.getCode());
//                    x.setDataMark(jobInitParam.getIsMonthDataMark());
//                    if(jobInitParam.getIsFirstSyncCategoryReport()){
//                        String id = monthSalesCompanyCategoryReportWriteRepository.add(x);
//                        log.info("<部门一级类目报表>新增部门一级类目报表,id=={},{}",id,JSON.toJSONString(x));
//                    }else{
//                        Map<String,Object> res = getAction(x,reportMap.get(x.getScItemCategoryId()),CATEGORY);
//                        log.info("<部门一级类目报表>计算数据完成后判断行动点结果,action={},old={},new={}",res.get("action"),JSON.toJSON(res.get("oldData")),x);
//                        if("add".equals(res.get("action"))){
//                            String id = monthSalesCompanyCategoryReportWriteRepository.add(x);
//                            log.info("<部门一级类目报表>新增部门一级类目报表2,id=={},{}",id,JSON.toJSONString(x));
//                        }else if("update".equals(res.get("action"))){
//                            int count = monthSalesCompanyCategoryReportWriteRepository.update(x);
//                            log.info("<部门一级类目报表>更新部门一级类目报表,更新了{}条数据,{}",count,JSON.toJSONString(x));
//                        }
//                    }
//                    pageUtil.sortNoIncrease();
//                };
//                pageUtil.turnPage();
//            }
//        }, monthSalesReportTaskExecutor);
//    }
//
//    @FacadeInvoker
//    private CompletableFuture<Void> executeGenerateCompanyTwoCategoryReport(JobInitParam jobInitParam){
//        return CompletableFuture.runAsync(() -> {
//            PageRecordUtil pageUtil = new PageRecordUtil();
//            pageUtil.resetPageParam();
//            CommPageQueryRequest queryRequest = CommPageQueryRequest.builder()
//                    .planMonth(jobInitParam.thisMonthTimestamp)
//                    .statDate(jobInitParam.getThisDay())
//                    .limit(pageUtil.getPageSize())
//                    .build();
//            //二级类目统计
//            queryRequest.setBizType(BizTypeEnum.TWO_CATEGORY.getCode());
//
//            //获取报表原数据
//            List<MonthSalesBasicReportSDO> oldReportList = jobInitParam.getIsFirstSyncEmployeeRank()?new ArrayList<>():queryOldReport(jobInitParam.getThisDay(),ONE_CATEGORY);
//            Map<String,MonthSalesBasicReportSDO> reportMap = Nullable.stream(oldReportList).collect(Collectors.toMap(MonthSalesBasicReportSDO::getManageEmployeeId, Function.identity(),(v1,v2)->v1));
//
//            for (int i = 1; i <= pageUtil.getPage(); i++) {
//                queryRequest.setStart(pageUtil.getStart());
//                PageResult<List<MonthSalesBasicReportSDO>> pageResult = monthSalesBasicReportQueryRepository.pageStatisticalMonthSalesCategory(queryRequest);
//                if(i == 1){
//                    pageUtil.setTotalPages(pageResult.getTotal());
//                }
//                for(MonthSalesBasicReportSDO x:pageResult.getContent()){
//                    //计算销售订单完成量
//                    countSalesOrderComplete(x);
//                    x.setBizType(BizTypeEnum.TWO_CATEGORY.getCode());
//                    x.setDataMark(jobInitParam.getIsMonthDataMark());
//                    if(jobInitParam.getIsFirstSyncCategoryReport()){
//                        String id = monthSalesCompanyCategoryReportWriteRepository.add(x);
//                        log.info("<部门二级类目报表>新增部门二级类目报表,id=={},{}",id,JSON.toJSONString(x));
//                    }else{
//                        Map<String,Object> res = getAction(x,reportMap.get(x.getScItemCategoryId()),CATEGORY);
//                        log.info("<部门二级类目报表>计算数据完成后判断行动点结果,action={},old={},new={}",res.get("action"),JSON.toJSON(res.get("oldData")),x);
//                        if("add".equals(res.get("action"))){
//                            String id = monthSalesCompanyCategoryReportWriteRepository.add(x);
//                            log.info("<部门二级类目报表>新增部门二级类目报表2,id=={},{}",id,JSON.toJSONString(x));
//                        }else if("update".equals(res.get("action"))){
//                            int count = monthSalesCompanyCategoryReportWriteRepository.update(x);
//                            log.info("<部门二级类目报表>更新部门二级类目报表,更新了{}条数据,{}",count,JSON.toJSONString(x));
//                        }
//                    }
//                    pageUtil.sortNoIncrease();
//                };
//                pageUtil.turnPage();
//            }
//        }, monthSalesReportTaskExecutor);
//    }

    private void enrichName(List<MonthSalesBasicReportSDO> list){
        //批量查询，补全主数据字段名称
        Set<String> orgBusinessUnitIds = new HashSet<>();
        Set<String> orgSalesOrganizationIds = new HashSet<>();
        Set<String> orgSalesChannelIds = new HashSet<>();
        Set<String> orgSalesDepartmentIds = new HashSet<>();
        Set<String> manageEmployeeIds = new HashSet<>();
        Set<String> customerCodes = new HashSet<>();
        Set<String> customerAddressCodes = new HashSet<>();
//        List<String> scItemRootCategoryIds = new ArrayList<>();
//        List<String> scItemLeafCategoryIds = new ArrayList<>();
        Set<String> scItemCategoryIds = new HashSet<>();
        Set<String> scItemCodes = new HashSet<>();

        list.forEach(x ->{
            if(StringUtil.isNotEmpty(x.getOrgBusinessUnitId())){
                orgBusinessUnitIds.add(x.getOrgBusinessUnitId());
            }
            if(StringUtil.isNotEmpty(x.getOrgSalesOrganizationId())){
                orgSalesOrganizationIds.add(x.getOrgSalesOrganizationId());
            }
            if(StringUtil.isNotEmpty(x.getOrgSalesChannelId())){
                orgSalesChannelIds.add(x.getOrgSalesChannelId());
            }
            if(StringUtil.isNotEmpty(x.getOrgSalesDepartmentId())){
                orgSalesDepartmentIds.add(x.getOrgSalesDepartmentId());
            }
            if(StringUtil.isNotEmpty(x.getManageEmployeeId())){
                manageEmployeeIds.add(x.getManageEmployeeId());
            }
            if(StringUtil.isNotEmpty(x.getCustomerCode())){
                customerCodes.add(x.getCustomerCode());
            }
            if(StringUtil.isNotEmpty(x.getCustomerAddressCode())){
                customerAddressCodes.add(x.getCustomerAddressCode());
            }
//            if(StringUtil.isNotEmpty(x.getScItemRootCategoryId())){
//                scItemRootCategoryIds.add(x.getScItemRootCategoryId());
//            }
//            if(StringUtil.isNotEmpty(x.getScItemLeafCategoryId())){
//                scItemLeafCategoryIds.add(x.getScItemLeafCategoryId());
//            }
            if(StringUtil.isNotEmpty(x.getScItemCategoryId())){
                scItemCategoryIds.add(x.getScItemCategoryId());
            }
            if(StringUtil.isNotEmpty(x.getScItemCode())){
                scItemCodes.add(x.getScItemCode());
            }
        });

        Map<String, OrganizationSDO> businessUnitMap = baseDataQueryRepository.batchQueryOrganization(Lists.newArrayList(orgBusinessUnitIds));
        Map<String, OrganizationSDO> salesOrganizationMap = baseDataQueryRepository.batchQueryOrganization(Lists.newArrayList(orgSalesOrganizationIds));
        Map<String, OrganizationSDO> salesChannelMap = baseDataQueryRepository.batchQueryOrganization(Lists.newArrayList(orgSalesChannelIds));
        Map<String, OrganizationSDO> salesDepartmentMap = baseDataQueryRepository.batchQueryOrganization(Lists.newArrayList(orgSalesDepartmentIds));
        Map<String, EmployeeSDO> emplyeeMap = baseDataQueryRepository.batchQueryEmplyee(Lists.newArrayList(manageEmployeeIds));
        Map<String, CustomerSDO> customerMap = baseDataQueryRepository.batchQueryCustomer(Lists.newArrayList(customerCodes));
        Map<String, CustomerAddressSDO> addressMap = baseDataQueryRepository.batchQueryCustomerAddressByCodes(Lists.newArrayList(customerAddressCodes));
        //Map<String, CategorySDO> rootCategoryMap = baseDataQueryRepository.batchQueryCategory(scItemRootCategoryIds);
        //Map<String, CategorySDO> leafCategoryMap = baseDataQueryRepository.batchQueryCategory(scItemLeafCategoryIds);
        Map<String, CategorySDO> categoryMap = baseDataQueryRepository.batchQueryCategory(Lists.newArrayList(scItemCategoryIds));
        Map<String, ScItemSDO> scItemMap = baseDataQueryRepository.batchQueryScItemDetail(Lists.newArrayList(scItemCodes));

        Set<String> nullNameCompanyOrgIds = new HashSet<>();
        Set<String> nullNameEmployeeIds = new HashSet<>();

        list.forEach(x ->{
            OrganizationSDO orgBusinessUnit = businessUnitMap.get(x.getOrgBusinessUnitId());
            x.setOrgBusinessUnitName(orgBusinessUnit !=null?orgBusinessUnit.getName():null);

            OrganizationSDO salesOrganization = salesOrganizationMap.get(x.getOrgSalesOrganizationId());
            x.setOrgSalesOrganizationName(salesOrganization !=null?salesOrganization.getName():null);

            if(StringUtil.isBlank(x.getOrgBusinessUnitId()) && salesOrganization !=null){
                x.setOrgBusinessUnitId(salesOrganization.getParentId());
                nullNameCompanyOrgIds.add(salesOrganization.getParentId());
            }
            if(StringUtil.isBlank(x.getOrgBusinessUnitId())){
                x.setOrgBusinessUnitId("-1");
                x.setOrgBusinessUnitName("其他");
            }

            OrganizationSDO salesChannel = salesChannelMap.get(x.getOrgSalesChannelId());
            if(salesChannel !=null){
                x.setOrgSalesChannelName(salesChannel.getName());
                x.setChannelManageEmployeeId(salesChannel.getLeaders());
                if(salesChannel.getFeatures() != null){
                    x.setChannelManageEmployeeName(salesChannel.getFeatures().get("leaders_name")!=null?(String)salesChannel.getFeatures().get("leaders_name"):null);
                }
            }else{
                if(x.getOrgSalesChannelId().contains("000")){
                    x.setOrgSalesChannelName("其他");
                }
            }

            OrganizationSDO salesDepartment = salesDepartmentMap.get(x.getOrgSalesDepartmentId());
            if(salesDepartment !=null){
                x.setOrgSalesDepartmentName(salesDepartment.getName());
                x.setOrgSalesDepartmentCode(salesDepartment.getCode());
                x.setDepartmentManageEmployeeId(salesDepartment.getLeaders());
                if(salesDepartment.getFeatures() != null) {
                    x.setDepartmentManageEmployeeName(salesDepartment.getFeatures().get("leaders_name") != null ? (String) salesDepartment.getFeatures().get("leaders_name") : null);
                    x.setDepartmentSimpleName(salesDepartment.getFeatures().get("simple_name") != null ? (String) salesDepartment.getFeatures().get("simple_name") : null);
                }
            }else{
                if(x.getOrgSalesDepartmentId().contains("000000")){
                    x.setOrgSalesDepartmentName("其他");
                }
            }

            EmployeeSDO emplyee = emplyeeMap.get(x.getManageEmployeeId());
            x.setManageEmployeeName(emplyee !=null?emplyee.getName():null);

            CustomerSDO customer = customerMap.get(x.getCustomerCode());
            x.setCustomerName(customer !=null?customer.getName():null);

            CustomerAddressSDO address = addressMap.get(x.getCustomerCode()+"#"+x.getCustomerAddressCode());
            if(address !=null){
                x.setCustomerAddressDesc(address.getAddressName());
                if(StringUtil.isBlank(x.getManageEmployeeId())){
                    x.setManageEmployeeId(address.getPrincipal());
                    nullNameEmployeeIds.add(address.getPrincipal());
                }
            }

            if(StringUtil.isBlank(x.getManageEmployeeId())){
                x.setManageEmployeeId("");
            }

//            CategorySDO rootCategory = rootCategoryMap.get(x.getScItemRootCategoryId());
//            x.setScItemRootCategoryName(rootCategory !=null?rootCategory.getCategoryName():null);
//
//            CategorySDO leafCategory = leafCategoryMap.get(x.getScItemLeafCategoryId());
//            x.setScItemLeafCategoryName(leafCategory !=null?leafCategory.getCategoryName():null);

            CategorySDO category = categoryMap.get(x.getScItemCategoryId());
            x.setScItemCategoryName(category !=null?category.getCategoryName():null);

            ScItemSDO scItem = scItemMap.get(x.getScItemCode());
            if(scItem !=null){
                //x.setScItemCode(scItem.getScItemId());
                x.setScItemOutCode(scItem.getOuterId());
                x.setScItemName(scItem.getTitle());
                x.setScItemLeafCategoryId(scItem.getLeafCategoryId());
                x.setScItemLeafCategoryName(scItem.getLeafCategoryName());
                x.setScItemRootCategoryId(scItem.getRootCategoryId());
                x.setScItemRootCategoryName(scItem.getRootCategoryName());
                if(scItem.getFeatures()!=null && scItem.getFeatures().get("scItemMarkType")!=null){
                    x.setScItemMark((String)scItem.getFeatures().get("scItemMarkType"));
                }
            }
        });

        Map<String, OrganizationSDO> companyOrgMap = baseDataQueryRepository.batchQueryOrganization(Lists.newArrayList(nullNameCompanyOrgIds));
        Map<String, EmployeeSDO> tmpEmployeeMap = baseDataQueryRepository.batchQueryEmplyee(Lists.newArrayList(nullNameEmployeeIds));
        list.forEach(x ->{
            if(StringUtil.isBlank(x.getOrgBusinessUnitName())){
                x.setOrgBusinessUnitName(companyOrgMap.get(x.getOrgBusinessUnitId())!=null?companyOrgMap.get(x.getOrgBusinessUnitId()).getName():null);
            }
            if(StringUtil.isBlank(x.getManageEmployeeName())){
                x.setManageEmployeeName(tmpEmployeeMap.get(x.getManageEmployeeId())!=null?tmpEmployeeMap.get(x.getManageEmployeeId()).getName():null);
            }
        });
    }

    @FacadeInvoker
    private List<MonthSalesBasicReportSDO> queryOldReport(String statisticalDate, String type){
        PageRecordUtil pageUtil = new PageRecordUtil();
        pageUtil.resetPageParam();
        //查询月度销售进度报表 old数据
        QueryMonthSalesReportRequest queryRequest = QueryMonthSalesReportRequest.builder()
                .statisticalDate(statisticalDate)
                .limit(pageUtil.getPageSize()*2)
                .build();
        List<MonthSalesBasicReportSDO> result = new ArrayList<>();
        for (int i = 1; i <= pageUtil.getPage(); i++) {
            queryRequest.setStart(pageUtil.getStart());
            PageResult<List<MonthSalesBasicReportSDO>> pageResult = null;
            if (BASIC.equals(type)) {
//            result = monthSalesBasicReportQueryRepository.pageQueryList(queryRequest);
            } else if (ONE_CATEGORY.equals(type)) {
                queryRequest.setBizType(BizTypeEnum.ONE_CATEGORY.getCode());
                pageResult = monthSalesCategoryReportQueryRepository.pageQueryList(queryRequest);
            } else if (TWO_CATEGORY.equals(type)) {
                queryRequest.setBizType(BizTypeEnum.TWO_CATEGORY.getCode());
                pageResult = monthSalesCategoryReportQueryRepository.pageQueryList(queryRequest);
            } else if (EMPLOYEE_RANK.equals(type)) {
                pageResult = monthSalesEmployeeRankReportQueryRepository.pageQueryList(queryRequest);
            } else if (DEPARTMENT_RANK.equals(type)) {
                pageResult = monthSalesDepartmentRankReportQueryRepository.pageQueryList(queryRequest);
            } else if (CHANNEL_RANK.equals(type)) {
                pageResult = monthSalesChannelRankReportQueryRepository.pageQueryList(queryRequest);
            }
            if(i == 1){
                pageUtil.setTotalPages(pageResult.getTotal());
            }
            result.addAll(pageResult.getContent());
            pageUtil.turnPage();
        }
        return result;
    }

    private Map<String,Object> getAction(MonthSalesBasicReportSDO sdo,MonthSalesBasicReportSDO oldSdo,String type){
        Map<String,Object> resultMap = new HashMap<>();
        List<String> equalFields = new ArrayList<>();
        if(BASIC.equals(type)){
            equalFields = Lists.newArrayList("taskCount","beforeMonthMoney","monthMoney",
                    "taskCountComplete","beforeMonthMoneyComplete","monthMoneyComplete",
                    "taskCountRemain","beforeMonthMoneyRemain","monthMoneyRemain",
                    "contractMoney","contractMoneyComplete","contractMoneyRemain");
        }else if(CATEGORY.equals(type)){
            equalFields = Lists.newArrayList("taskCount","beforeMonthMoney","monthMoney",
                    "taskCountComplete","beforeMonthMoneyComplete","monthMoneyComplete",
                    "taskCountRemain","beforeMonthMoneyRemain","monthMoneyRemain",
                    "contractMoney","contractMoneyComplete","contractMoneyRemain");
        }else if(EMPLOYEE_RANK.equals(type)){
            equalFields = Lists.newArrayList("taskCount","beforeMonthMoney","monthMoney",
                    "taskCountComplete","beforeMonthMoneyComplete","monthMoneyComplete",
                    "taskCountRemain","beforeMonthMoneyRemain","monthMoneyRemain",
                    "taskCountCompleteRankNo","beforeMonthMoneyCompleteRankNo","monthMoneyCompleteRankNo",
                    "contractMoney","contractMoneyComplete","contractMoneyRemain","contractMoneyCompleteRankNo");
        }else if(DEPARTMENT_RANK.equals(type)){
            equalFields = Lists.newArrayList("taskCount","beforeMonthMoney","monthMoney",
                    "taskCountComplete","beforeMonthMoneyComplete","monthMoneyComplete",
                    "taskCountRemain","beforeMonthMoneyRemain","monthMoneyRemain",
                    "taskCountCompleteRankNo","beforeMonthMoneyCompleteRankNo","monthMoneyCompleteRankNo",
                    "contractMoney","contractMoneyComplete","contractMoneyRemain","contractMoneyCompleteRankNo");
        }else if(CHANNEL_RANK.equals(type)){
            equalFields = Lists.newArrayList("taskCount","beforeMonthMoney","monthMoney",
                    "taskCountComplete","beforeMonthMoneyComplete","monthMoneyComplete",
                    "taskCountRemain","beforeMonthMoneyRemain","monthMoneyRemain",
                    "taskCountCompleteRankNo","beforeMonthMoneyCompleteRankNo","monthMoneyCompleteRankNo",
                    "contractMoney","contractMoneyComplete","contractMoneyRemain","contractMoneyCompleteRankNo");
        }
        if(oldSdo == null){
            resultMap.put("oldData",null);
            resultMap.put("action","add");
            return resultMap;
        }

        if(ObjectEqualsUtil.domainEquals(sdo, oldSdo, equalFields)){
            resultMap.put("oldData",oldSdo);
            resultMap.put("action","noAction");
        }else{
            resultMap.put("oldData",oldSdo);
            resultMap.put("action","update");
        }
        return resultMap;
    }

    private void countSalesOrderComplete(MonthSalesBasicReportSDO sdo){
        //任务量
        BigDecimal taskCount = new BigDecimal(sdo.getTaskCount());
        //折前任务金额
        BigDecimal beforeMonthMoney = sdo.getBeforeMonthMoney().setScale(2, BigDecimal.ROUND_HALF_UP);;
        sdo.setBeforeMonthMoney(beforeMonthMoney);
        //折后任务金额
        BigDecimal monthMoney = sdo.getMonthMoney().setScale(2, BigDecimal.ROUND_HALF_UP);
        sdo.setMonthMoney(monthMoney);
        //折后合同金额
        BigDecimal contractMoney = sdo.getContractMoney().setScale(2, BigDecimal.ROUND_HALF_UP);
        sdo.setContractMoney(contractMoney);

        //任务达成量
        BigDecimal taskCountComplete  = new BigDecimal(sdo.getTaskCountComplete());
        //折前任务金额达成量
        BigDecimal beforeMonthMoneyComplete = sdo.getBeforeMonthMoneyComplete().setScale(2, BigDecimal.ROUND_HALF_UP);
        sdo.setBeforeMonthMoneyComplete(beforeMonthMoneyComplete);
        //折后任务金额达成量  折后合同金额达成量
        BigDecimal monthMoneyComplete = sdo.getMonthMoneyComplete().setScale(2, BigDecimal.ROUND_HALF_UP);
        sdo.setMonthMoneyComplete(monthMoneyComplete);
        sdo.setContractMoneyComplete(monthMoneyComplete);

        //任务达成量百分比
        BigDecimal taskCountCompletePercentage = taskCount.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):taskCountComplete.divide(taskCount,4,BigDecimal.ROUND_HALF_UP);
        sdo.setTaskCountCompletePercentage(taskCountCompletePercentage);
        //折前任务金额达成百分比
        BigDecimal beforeMonthMoneyCompletePercentage = beforeMonthMoney.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):beforeMonthMoneyComplete.divide(beforeMonthMoney,4,BigDecimal.ROUND_HALF_UP);
        sdo.setBeforeMonthMoneyCompletePercentage(beforeMonthMoneyCompletePercentage);
        //折后任务金额达成百分比
        BigDecimal monthMoneyCompletePercentage = monthMoney.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):monthMoneyComplete.divide(monthMoney,4,BigDecimal.ROUND_HALF_UP);
        sdo.setMonthMoneyCompletePercentage(monthMoneyCompletePercentage);
        //折后合同金额达成百分比
        BigDecimal contractMoneyCompletePercentage = contractMoney.compareTo(new BigDecimal(0)) == 0?new BigDecimal(0.00):monthMoneyComplete.divide(contractMoney,4,BigDecimal.ROUND_HALF_UP);
        sdo.setContractMoneyCompletePercentage(contractMoneyCompletePercentage);

        //任务差量
        BigDecimal taskCountRemain = taskCountComplete.subtract(taskCount);
        sdo.setTaskCountRemain(taskCountRemain.longValue());
        //折前任务差额
        BigDecimal beforeMonthMoneyRemain = beforeMonthMoneyComplete.subtract(beforeMonthMoney);
        sdo.setBeforeMonthMoneyRemain(beforeMonthMoneyRemain);
        //折后任务差额
        BigDecimal monthMoneyRemain = monthMoneyComplete.subtract(monthMoney);
        sdo.setMonthMoneyRemain(monthMoneyRemain);
        //折后合同差额
        BigDecimal contractMoneyRemain = monthMoneyComplete.subtract(contractMoney);
        sdo.setContractMoneyRemain(contractMoneyRemain);
    }

    private MonthSalesBasicReportSDO addReportDataSDOConverter(MonthSalesPlanProgressReportSDO sdo){
        MonthSalesBasicReportSDO bean = new MonthSalesBasicReportSDO();
        bean.setOrgBusinessUnitId(sdo.getOrgBusinessUnitCode());
        bean.setOrgSalesOrganizationId(sdo.getOrgSalesOrganizationCode());
        bean.setOrgSalesChannelId(StringUtils.isNotBlank(sdo.getOrgSalesChannelCode())?sdo.getOrgSalesChannelCode():"000"+bean.getOrgSalesOrganizationId());
        bean.setOrgSalesDepartmentId(StringUtils.isNotBlank(sdo.getOrgSalesDepartmentCode())?sdo.getOrgSalesDepartmentCode():"000"+bean.getOrgSalesChannelId());
        bean.setManageEmployeeId(sdo.getManageEmployeeId());
        bean.setCustomerCode(sdo.getCustomerCode());
        bean.setCustomerAddressCode(sdo.getCustomerAddressCode());
        bean.setScItemRootCategoryId(sdo.getScItemRootCategoryId());
        bean.setScItemLeafCategoryId(sdo.getScItemLeafCategoryId());
        bean.setScItemCode(sdo.getScItemId());
        bean.setPlanTime(sdo.getPlanTime());
        bean.setTaskCount(sdo.getTaskCount());
        bean.setBeforeMonthMoney(sdo.getBeforeMonthMoney());
        bean.setMonthMoney(sdo.getMonthMoney());
        return bean;
    }

    @Override
    @FacadeInvoker
    public Result<Void> generateMonthSalesBasicReportJob(){
        //初始化参数
        JobInitParam jobInitParam = init(null);
        //生成月度销售基础报表
        executeGenerateMonthSalesBasicReport(jobInitParam);
        return Result.success(null);
    }
    @Override
    @FacadeInvoker
    public Result<Void> generateMonthSalesEmployeeRankReportJob(){
        //初始化参数
        JobInitParam jobInitParam = init(null);
        //生成月度销售员工排名报表
        CompletableFuture<Void> task1 = executeGenerateEmployeeRankReport(jobInitParam);
        CompletableFuture.allOf(task1).join();
        return Result.success(null);
    }
    @Override
    @FacadeInvoker
    public Result<Void> generateMonthSalesDepartmentRankReportJob(){
        //初始化参数
        JobInitParam jobInitParam = init(null);
        //生成月度销售部门排名报表
        CompletableFuture<Void> task1 = executeGenerateDepartmentRankReport(jobInitParam);
        CompletableFuture.allOf(task1).join();
        return Result.success(null);
    }
    @Override
    @FacadeInvoker
    public Result<Void> generateMonthSalesChannelRankReportJob(){
        //初始化参数
        JobInitParam jobInitParam = init(null);
        //生成月度销售渠道排名报表
        CompletableFuture<Void> task1 = executeGenerateChannelRankReport(jobInitParam);
        CompletableFuture.allOf(task1).join();
        return Result.success(null);
    }

    @Override
    @FacadeInvoker
    public Result<Void> generateMonthSalesCategoryReportJob() {
        //初始化参数
        JobInitParam jobInitParam = init(null);
        //生成月度销售部门品类报表
        CompletableFuture<Void> task1 = executeGenerateOneCategoryReport(jobInitParam);
        CompletableFuture<Void> task2 = executeGenerateTwoCategoryReport(jobInitParam);
        CompletableFuture.allOf(task1,task2).join();
        return Result.success(null);
    }

    @Override
    @FacadeInvoker
    public Result<Void> batchGenerateAllMonthSalesReportJob(BatchGenerateAllMonthSalesReportJobRequest batchGenerateAllMonthSalesReportJobRequest){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date beginStatisticalDate = null;
        Date endStatisticalDate = null;
        try {
            beginStatisticalDate = format.parse(batchGenerateAllMonthSalesReportJobRequest.getBeginStatisticalDate());
            endStatisticalDate = format.parse(batchGenerateAllMonthSalesReportJobRequest.getEndStatisticalDate());
        } catch (ParseException e) {
            return Result.fail("","入参日期格式错误");
        }
        if(beginStatisticalDate.getTime()>endStatisticalDate.getTime()){
            return Result.fail("","开始统计日期大于结束统计日期");
        }
        int betweenDays = DomUtil.getBetweenDays(batchGenerateAllMonthSalesReportJobRequest.getBeginStatisticalDate(),batchGenerateAllMonthSalesReportJobRequest.getEndStatisticalDate());
        if(betweenDays >31 ){
            return Result.fail("","开始结束统计日期间隔过大");
        }

        String statisticalDate = batchGenerateAllMonthSalesReportJobRequest.getBeginStatisticalDate();
        for(int i = 1; i<=31; i++){
            if(i!=1){
                statisticalDate = DomUtil.getRollbackDate(DateUtils.parse(statisticalDate),1);
            }
            if(statisticalDate.equals(DomUtil.getRollbackDate(endStatisticalDate,1))){
                break;
            }
            log.info("batchGenerateAllMonthSalesReportJob_start,{}",statisticalDate);
            GenerateAllMonthSalesReportJobRequest request = new GenerateAllMonthSalesReportJobRequest();
            request.setStatisticalDate(statisticalDate);
            request.setSlowerMode(true);
            try {
                Result<Void> result = generateAllMonthSalesReportJob(request);
            } catch (Exception e) {
                log.error("batchGenerateAllMonthSalesReportJob_statistical_occur_error,statisticalDate={},{}",statisticalDate,e.getMessage());
            }
            log.info("batchGenerateAllMonthSalesReportJob_end,{}",statisticalDate);
            try {
                Thread.sleep(10000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return Result.success(null);
    }

    @Override
    @FacadeInvoker
    public Result<Void> generateOneMonthSalesReportJob() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        String yesterday = DomUtil.getYesterday();
        String beginStatisticalDate = DomUtil.getRollbackDate(DateUtils.parse(yesterday),-14);
        BatchGenerateAllMonthSalesReportJobRequest request = new BatchGenerateAllMonthSalesReportJobRequest();
        request.setBeginStatisticalDate(beginStatisticalDate);
        request.setEndStatisticalDate(yesterday);
        Result<Void> result = batchGenerateAllMonthSalesReportJob(request);
        stopWatch.stop();
        log.info("generateOneMonthSalesReportJob_consume_seconds={}", stopWatch.getTotalTimeSeconds());
        return Result.success(null);
    }

    @Data
    private class JobInitParam{

        private Date todayDate;

        private String thisDay;

        private String thisMonth;

        private String thisYear;

        private String thisMonthTimestamp;

        private String month;

        private Integer isMonthDataMark;

        private Boolean isFirstSyncBasicReport;

        private Boolean isFirstSyncEmployeeRank;

        private Boolean isFirstSyncDepartmentRank;

        private Boolean isFirstSyncChannelRank;

        private Boolean isFirstSyncCategoryReport;

        private String enterpriseGroupOrgId;

        private Boolean slowerMode = false;

    }

}
